17
\$\begingroup\$

The challenge

The program must return all numbers included into a group (comma and hyphen separated sequence) of numbers.

Rules

  • s is the sequence string;
  • all numbers included in s are positive;
  • numbers will always increase;
  • numbers will never repeat
  • when you answer, show the output for s="1,3-5,9,16,18-23"

Examples

input(s) outputs
-----------------
1 1
1,2 1,2
1-4 1,2,3,4
1-4,6 1,2,3,4,6
1-4,8-11 1,2,3,4,8,9,10,11

Good luck. =)

lirtosiast
21.6k5 gold badges53 silver badges127 bronze badges
asked Oct 3, 2012 at 16:25
\$\endgroup\$
5
  • 1
    \$\begingroup\$ Will we ever have input sequences that are not constantly increasing, for example: 4-9,1-2 or 1-3,9-6? \$\endgroup\$ Commented Oct 3, 2012 at 17:16
  • 1
    \$\begingroup\$ Or overlapping? Does the output have to be sorted and not contain duplicates? \$\endgroup\$ Commented Oct 3, 2012 at 17:24
  • \$\begingroup\$ @Gareth Yes, this is a code-golf, then please vote-up for the shortest answer. Matt and Peter, I edited the question, please check it. Thanks! \$\endgroup\$ Commented Oct 3, 2012 at 17:33
  • \$\begingroup\$ Does it have to be a full program, and is there a restriction on the format of the output? \$\endgroup\$ Commented Nov 28, 2015 at 19:21
  • 1
    \$\begingroup\$ duplicate? \$\endgroup\$ Commented Nov 28, 2015 at 21:53

31 Answers 31

1
2
7
\$\begingroup\$

Perl (削除) 25 (削除ここまで) (削除) 26 (削除ここまで) 25

$_ is the sequence string

s/-/../g;$_=join",",eval

Sample session:

[~/] $ perl -M5.010 -pe 's/-/../g;$_=join",",eval' <<< "1,3-5,9,16,18-23"
1,3,4,5,9,16,18,19,20,21,22,23

Added 1 character to the character count for the (削除) -n (削除ここまで)-p option (thanks Gareth, ..kinda).

answered Oct 3, 2012 at 18:49
\$\endgroup\$
3
  • \$\begingroup\$ I've probably done the character counting wrong (with the command line options). Feel free to correct my counting, please \$\endgroup\$ Commented Oct 3, 2012 at 18:57
  • \$\begingroup\$ Going by the answer to this question on meta, you only need to add 1 character for the n option. \$\endgroup\$ Commented Oct 3, 2012 at 19:03
  • \$\begingroup\$ Remove -M5.010 and exchange -e for -E \$\endgroup\$ Commented Nov 28, 2015 at 19:31
6
\$\begingroup\$

GolfScript (24 chars)

','/{~.,!{~)),>~}*}%','*

E.g.

$ golfscript.rb expand.gs <<<"1,3-5,9,16,18-23"
1,3,4,5,9,16,18,19,20,21,22,23

I actually have four 24-char solutions, but I chose this one because it doesn't have any alphanumeric characters.

How it works

# On the stack: a string such as "1,3-5,9,16,18-23"
','/
# Split on commas to get ["1" "3-5" "9" "16" "18-23"]
{
 # This is executed for each of those strings in a map
 # So stack holds e.g. "1" or "3-5"
 # Evaluate the string.
 # If it's a single number, this puts the number on the stack.
 # Otherwise it's parsed as a positive number followed by a negative number.
 ~
 # Stack holds e.g. 1 or 3 -5
 # Duplicate the last element on the stack and make a list of that length.
 # If it's negative or zero, the list will be empty
 .,
 # Negate. An empty list => 1; a non-empty list => 0
 !
 # If the string was a single number "n", the stack now holds n 0
 # If the string was a range "m-n", the stack now holds m -n 1
 # The following block will be executed 0 times for "n" and once for "m-n"
 {
 # Here we rely on twos-complement numbers satisfying ~n = -n -1
 # Stack: m -n
 ~))
 # Stack: m -(-n)-1+2 = m n+1
 ,
 # Stack: m [0 1 2 ... n]
 >
 # Stack: [m m+1 ... n]
 ~
 # Stack: m m+1 ... n
 }*
}%
# On the stack: e.g. [1 3 4 5 9 16 18 19 20 21 22 23]
','*
# Joined by , to give the desired output
answered Oct 3, 2012 at 22:46
\$\endgroup\$
2
  • \$\begingroup\$ How can you expand 3-5 into 3,4,5 without using a single the character -? \$\endgroup\$ Commented Oct 4, 2012 at 20:20
  • \$\begingroup\$ @BernaMariano, sorry, I somehow missed your question. I'll expand the answer with a detailed explanation. \$\endgroup\$ Commented Nov 9, 2012 at 21:53
4
\$\begingroup\$

golfscript, (削除) 46 (削除ここまで) 45

My first ever golf script program, took hours to complete.

{','/{'-'/{~}%.,1-{))+{,}/\-~}{~}if}%","*}:r; 
# call:
"1,3-5,9,16,18-23"r
# return:
1,3,4,5,9,16,18,19,20,21,22,23

You can try it at http://golfscript.apphb.com/

My best throw at explaining this atrocity:

{...}:r; # makes a function block ... and names it r
','/ # slices the top element of stack from each ','
 # so we get ["1" "3-5" "9" "16" "18-23"]
{...}% # makes a function block ... and calls it for 
 # each element in the list
'-'/{~}% # slices the list by '-' and evals each element 
 # from string to int. ["1"] becomes [1], 
 # ["3-5"] becomes [3 5]
.,1- # adds the length of the list -1 on top of the stack
 # so for [1] the stack becomes [1] 0, for [3 5]
 # it becomes [3 5] 1
# next we add two function blocks, they, like the 0/1 just before
# are used by an if clause a tiny bit later. First block is for 
# lists that have a 1 on top of them, the latter for ones with 0.
# First block, we have something like [3 5]
))+ # pops the top element of the array, increments 
 # it and puts back. [3 6]
## It seems {...}%~ is same as {...}/
## this is why these two are not in the code any more
{,}% # , makes a list from 0 to n-1, where n is the parameter
 # so we get [[0 1 2] [0 1 2 3 4 5]]
~ # Dumps the outer array, [0 1 2] [0 1 2 3 4 5]
\ # swaps the two arrays
- # set complement [3 4 5]
~ # dumps the array, so the elements are left in the stack
# Second block, we have something like [16]
~ # just dumps the array, 16
# Blocks end
if # takes the top three elements of the stack, evaluates the 
 # first (0 or 1), runs second if true (anything but 
 # [], "", 0 or {} ), otherwise the third.
","* # joins an array with ","

edit 1: changed the last {}%~ to {}/, also my description was likely wrong.

answered Oct 3, 2012 at 20:34
\$\endgroup\$
4
  • 2
    \$\begingroup\$ +1, because anyone doing a program in GolfScript has earned it. \$\endgroup\$ Commented Oct 3, 2012 at 21:37
  • \$\begingroup\$ @Gareth Thanks. I first thought I'd just do it the perl way: change - to .. and evaluate it. Then I couldn't find any sane way to build any arrays so I did this. I'm sure someone will come around with a ~20 char solution with golfscript. \$\endgroup\$ Commented Oct 3, 2012 at 22:20
  • \$\begingroup\$ I have 24 at the moment, so I'll take 20 as a challenge ;) You can save a few quite easily, though. The problem asks for a program, not a function, so you can lose the initial { and the final }:r; and you can also save one by replacing 1- with (. (Incidentally, IIRC that's one trick I also missed in my first GolfScript program) \$\endgroup\$ Commented Oct 3, 2012 at 22:32
  • \$\begingroup\$ PS There is a subtle difference between {...}%~ and {...}/. If you're accessing something further down the stack using integer $ then the first one is simpler, because you don't have to adjust the integer each time to compensate for whatever you're leaving on the stack. \$\endgroup\$ Commented Oct 3, 2012 at 22:34
4
\$\begingroup\$

R, 44 bytes

`-`=seq;eval(parse(t=c("c(",scan(,""),")")))

Try it online!

Redefine - to mean seq (i.e. :), surround the input with c() and evaluate the corresponding expression.

answered Jun 24, 2019 at 21:14
\$\endgroup\$
3
\$\begingroup\$

Jelly, 9 bytes

)-ryṣ",VF

Try it online!

 y Replace
)-r hyphens with the letter r,
 ṣ", split on commas,
 V evaluate every element,
 F and flatten.

The range dyad r takes two arguments on either side of it and produces an inclusive range between them.

answered Jun 24, 2019 at 19:01
\$\endgroup\$
3
\$\begingroup\$

Wolfram Language (Mathematica), 57 bytes

{Plus=##&@@#~Range~-#2&}~Block~ToExpression["{"<>#<>"}"]&

Try it online!

 "{"<>#<>"}" wrap in {}
{Plus=##&@@#~Range~-#2&}~Block~ interpret - as spliced range:
 ToExpression[ ] parse
answered Dec 21, 2024 at 9:40
\$\endgroup\$
2
\$\begingroup\$

K, 47

","/:,/${x+!1+y-x}.'2#'a,'a:"I"$'"-"\:'","\:0:0

Test case

k)","/:,/${x+!1+y-x}.'2#'a,'a:"I"$'"-"\:'","\:0:0
1,3-5,9,16,18-23
"1,3,4,5,9,16,18,19,20,21,22,23"
answered Oct 3, 2012 at 20:01
\$\endgroup\$
1
  • \$\begingroup\$ ","/:,ドル/{{x+!1+y-x}. 2#"J"$"-"\:x}'","\:0:0 for 43 bytes \$\endgroup\$ Commented Jul 19, 2019 at 21:45
2
\$\begingroup\$

05AB1E, 10 bytes

',¡ε'-¡Ÿ} ̃

Input as a string; output as a list of integers.

Try it online or verify all test cases.

Explanation:

',¡ '# Split the (implicit) input-string on ","
 ε # Map over each substring:
 '-¡ '# Split the substring on "-"
 Ÿ # Convert the pair to a list in that range
 # (if it's a singleton, it'll remain as is)
 } ̃ # After the map: flatten the list of lists
 # (after which the result is output implicitly)
answered Dec 17, 2024 at 12:10
\$\endgroup\$
2
\$\begingroup\$

Retina, 32 bytes

\d+
*
vr`(?<!1円)-(_+)
,1ドル
_+
$.0

Try it online!

Don't really feel good about this, but after spinning my wheels on it on and off basically all morning I'd feel even worse not posting...

Explanation:

\d+
*

Convert each run of digits to unary with underscores as the digit.

vr`(?<!1円)-(_+)
,1ドル

Take overlapping RtL matches of a hyphen and a run of underscores (possibly non-maximal--overlapping RtL tries matching leftwards from each position, such that e.g. vr`.+ matches every prefix), provided that the hyphen is NOT directly preceded by that many or more underscores (not part of the match), and substitute the underscores after a comma. Overlapping matches are weird and I'm not entirely sure how to describe the behavior here, but the way I understand it is more or less anything that none of them match is a "separator" and the match substitutions and separators just get smushed back together in the order of their starting positions.

_+
$.0

Convert each run of underscores to its length in decimal.

answered Dec 21, 2024 at 19:24
\$\endgroup\$
1
  • \$\begingroup\$ On further inspection of the docs (i.e. actually reading them instead of skimming), the way separators are determined with overlapping matches is a little different (it's possible for something to be part of both a match and a separator so long as the match isn't one of the pair of matches it separates), but there's no difference to this program because the matches form a poset w.r.t. substring-ness. \$\endgroup\$ Commented Dec 23, 2024 at 14:34
1
\$\begingroup\$

Perl (37)

$_=<>;s/^/say join',',/;s/-/../g;eval
answered Oct 3, 2012 at 16:48
\$\endgroup\$
2
  • \$\begingroup\$ - when you answer, show the output for s="1,3-5,9,16,18-23", thanks \$\endgroup\$ Commented Oct 3, 2012 at 17:40
  • \$\begingroup\$ How about say join",",eval<>=~s/-/../gr at 29 bytes \$\endgroup\$ Commented Nov 28, 2015 at 19:15
1
\$\begingroup\$

J, (削除) 53 (削除ここまで) (削除) 43 (削除ここまで) (削除) 41 (削除ここまで) (削除) 39 (削除ここまで) 38 characters

;(}.[:i.1+])/&.>".'- ,;'charsub 1!:1[1

Takes input from the keyboard:

 ;(}.[:i.1+])/&.>".'- ,;'charsub 1!:1[1
1-4,8-11
1 2 3 4 8 9 10 11

Output for the requested test case:

 ;(}.[:i.1+])/&.>".'- ,;'charsub 1!:1[1
1,3-5,9,16,18-23
1 3 4 5 9 16 18 19 20 21 22 23
answered Oct 3, 2012 at 16:56
\$\endgroup\$
0
1
\$\begingroup\$

Hassium, 173 Bytes

This was pretty long and might not be competing since there is a trailing , at the end.

 func main(){p="1,2,3,5-8".split(",")for(c=0;c<p.length;c++){e=p[c]if(e.contains("-")){p=e.split("-")for(x=p[0].toInt();x<=p[1].toInt()print(x++ +",")){}}else print(e+",")}}

Run online and see expanded here

answered Nov 25, 2015 at 15:41
\$\endgroup\$
1
\$\begingroup\$

Python 2.7, (削除) 147 (削除ここまで) 138 Bytes

z,f=input().split(','),[]
for i in z:
 x=i.split('-')
 if len(x)>1:f+=range(int(x[0]),int(x[1])+1)
 else:f+=[int(x[0])]
print str(f)[1:-1]

Usage:

>>>python nums.py
"1,3-5,9,16,18-23"
1, 3, 4, 5, 9, 16, 18, 19, 20, 21, 22, 23

Not the best program...

answered Nov 26, 2015 at 1:24
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Welcome to PPCG. I think you can make your answer shorter by using 1 space for indents. \$\endgroup\$ Commented Nov 26, 2015 at 2:42
  • \$\begingroup\$ Thanks @intrepidcoder, I didn't know that you could use single space indents. \$\endgroup\$ Commented Nov 27, 2015 at 1:26
1
\$\begingroup\$

PowerShell, (削除) 79 (削除ここまで) 71 bytes

('('+($args[0]-replace'-','..'-replace',','),(')+')'|iex|%{$_})-join','

Try it online!

The inner part changes "1,5-9,12" into a "(1),(5..9),(12)" format that PowerShell understands, then executes that with iex, which creates an array of arrays. Then iterate through each inner array, then finally join all outer array elements together

Borrows code from my "Help Me Manage My Time" answer

Usage

PS C:\Tools\Scripts\golfing> .\return-each-number-from-a-group-of-numbers.ps1 '1,3-5,9,16,18-23'
1,3,4,5,9,16,18,19,20,21,22,23

-8 bytes thanks to Veskah

answered Nov 25, 2015 at 13:49
\$\endgroup\$
1
1
\$\begingroup\$

Ruby -p, 33 bytes

gsub(/(\d+)-(\d+)/){[*1ドル..2ドル]*?,}

Try it online!

answered Jun 25, 2019 at 21:47
\$\endgroup\$
1
\$\begingroup\$

K (oK), (削除) 40 (削除ここまで) 31 bytes

Solution

,/{{x+!1+y-x}. 2#.:'"-"\x}'","\

Try it online!

Explanation:

Managed more golfing whilst adding the explanation...

,/{{x+!1+y-x}. 2#.:'"-"\x}'","\ / the solution
 ","\ / split input on ","
 { }' / apply lambda to each
 "-"\x / split x on "-"
 .:' / value (.:) each (')
 2# / 2 take (dupe if only 1 element)
 { }. / diadic lambda, 2 args x and y
 y-x / y subtract x
 1+ / add 1
 ! / range 0..n
 x+ / add x
,/ / flatten
answered Jul 19, 2019 at 21:19
\$\endgroup\$
1
\$\begingroup\$

Husk, 11 bytes

ṁȯ...mix'-x',

Try it online!

answered Jan 21, 2021 at 3:22
\$\endgroup\$
1
\$\begingroup\$

Wolfram Language (Mathematica), 108 bytes

Flatten[If[StringContainsQ[#,"-"],Range@@ToExpression@StringSplit[#,"-"],FromDigits@#]&/@StringSplit[s,","]]

Try it online!

answered Dec 17, 2024 at 14:03
\$\endgroup\$
1
\$\begingroup\$

JavaScript, 59 bytes

f=x=>x.replace(/(\d+)-(\d+)/g,(_,a,b)=>a-b?[f(a+-~-b),b]:a)

Try it online!

answered Dec 18, 2024 at 0:54
\$\endgroup\$
1
\$\begingroup\$

Pyth, 17 bytes

.nm.U}bZvcd\-cz,円

Try this online!

Explanation:

.nm.U}bZvcd\-cz,円
 cz,円 => split on commas
 m => map
 vcd\- => split on hypens and parse each
 .U => reduce
 }bZ => [A, A+1, ..., B]
.n => flatten list
answered Dec 18, 2024 at 1:11
\$\endgroup\$
1
\$\begingroup\$

Kotlin, 105 bytes

{it.split(",").joinToString(","){it.split("-").run{(first().toInt()..last().toInt()).joinToString(",")}}}

Try it online!

val f:(String)->String= is the header. Just splits the string with the , delimiter, and for every element it can only be 1 or 2 elements after it's split by -

After that, it creates the range of numbers, using first() and last() allows it to work whether it has one or two elements, and then just joins the characters again with , and joined again by , after all ranges are processed

answered Dec 18, 2024 at 3:17
\$\endgroup\$
1
\$\begingroup\$

Red, 150 bytes

func[s][replace/all s","" "replace/all s"-"" - "b: make bitset! t: to[]load s
u: copy""repeat n v: last t[if b/:n[append u n if n < v[append u","]]]u]

Try it online!

The input is very close to the way Red constructs bitset!datatype - the difference is that the numbers must be separated by spaces and not commas, and the hyphen also must be enclosed in spaces - for example [1 - 4 6]. When this is done we can simply make bitset! from the loaded block. Then we need to iterate over the range from 1 to the last numebr and check if the current value is set in our bitset!. The last thing is to format the output - a siginficant part of the program is dealing with joining the values with commas :)

answered Dec 18, 2024 at 9:25
\$\endgroup\$
1
\$\begingroup\$

Zsh +sed, 64 bytes

eval echo `sed -E 's/,/ /g;s/([0-9]+)-([0-9]+)/{1円..2円}/g'<<<1ドル`

Try it online!

sed -E converts string 1,3-5,9,16,18-23 into 1 {3..5} 9 16 {18..23} so that Zsh can apply brace expansion.

answered Dec 21, 2024 at 12:30
\$\endgroup\$
0
\$\begingroup\$

MATLAB, 47 bytes

disp(eval(['[',strrep(input(''),'-',':'),']']))

This snippet reads a string input from the command window, replaces '-' by ':', adds square brackets to the string and then evaluates it, so that the input will be expanded to a full array of numbers.

Example input:

'1,3-5,9,16,18-23'

Example output:

1 3 4 5 9 16 18 19 20 21 22 23

I believe this output is allowed, as the challenge only say that all numbers in a group should be displayed.

answered Nov 27, 2015 at 9:22
\$\endgroup\$
1
  • \$\begingroup\$ comma-separated output would be nicer, though i can se a 5-spaces-separated pattern, thats cool for me :) \$\endgroup\$ Commented Nov 27, 2015 at 14:05
0
\$\begingroup\$

Perl 6, 36 bytes

$_=get;say join ',',EVAL S:g/\-/../
1,3,4,5,9,16,18,19,20,21,22,23
answered Nov 28, 2015 at 19:12
\$\endgroup\$
0
\$\begingroup\$

Clojure, 110 bytes

#(clojure.string/join","(for[s(.split %",")[a b][(map read-string(.split s"-"))]r(if b(range a(inc b))[a])]r))

Dealing with strings isn't much fun :(

answered Jun 25, 2019 at 13:23
\$\endgroup\$
0
\$\begingroup\$

Python 2, 112 bytes

Pretty simple and straightforward answer.

L=[]
for s in input().split(','):
 if'-'in s:a,b=map(int,s.split('-'));L+=range(a,b+1)
 else:L+=[int(s)]
print L

Try it online!

answered Jun 25, 2019 at 14:55
\$\endgroup\$
0
\$\begingroup\$

Japt, 12 bytes

q, c@OvXr-'ò

Try it

answered Jul 19, 2019 at 17:28
\$\endgroup\$
2
  • \$\begingroup\$ Can you replace c@ with £? \$\endgroup\$ Commented Jul 19, 2019 at 20:07
  • \$\begingroup\$ @Oliver, as it's an old challenge that doesn't specify its I/O format, I erred on the side of caution, taking input as a comma delimited string and outputting as a flattened array. Normally, though, yes, I'd have specified input as an array of strings, output as a multi-dimensional array and just used £ in place of the first 5 bytes. \$\endgroup\$ Commented Jul 19, 2019 at 20:49
0
\$\begingroup\$

Python 2, 90 bytes

lambda s:sum((range(u[0],u[-1]+1)for u in[map(int,t.split('-'))for t in s.split(',')]),[])

Try it online!

answered Jul 22, 2019 at 20:03
\$\endgroup\$
0
\$\begingroup\$

Lua (126 bytes)

Just for fun:

(("1,3-5,9,16,18-23"):gsub("(%d+)-(%d+)",function(a,b)t={}for i=a,b do t[#t+1]=math.ceil(i)end return table.concat(t,",")end))
answered Jan 21, 2021 at 3:54
\$\endgroup\$
1
2

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.