# Return each number from a group of numbers

## 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. =)

-
Will we ever have input sequences that are not constantly increasing, for example: `4-9,1-2` or `1-3,9-6`? – Matt Oct 3 '12 at 17:16
Or overlapping? Does the output have to be sorted and not contain duplicates? – Peter Taylor Oct 3 '12 at 17:24
@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! – BernaMariano Oct 3 '12 at 17:33
Does it have to be a full program, and is there a restriction on the format of the output? – Brad Gilbert b2gills Nov 28 '15 at 19:21
duplicate? – ev3commander Nov 28 '15 at 21:53

## 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
``````
-
How can you expand 3-5 into 3,4,5 without using a single the character `-`? – BernaMariano Oct 4 '12 at 20:20
@BernaMariano, sorry, I somehow missed your question. I'll expand the answer with a detailed explanation. – Peter Taylor Nov 9 '12 at 21:53

## Perl 2526 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).

-
I've probably done the character counting wrong (with the command line options). Feel free to correct my counting, please – ardnew Oct 3 '12 at 18:57
Going by the answer to this question on meta, you only need to add 1 character for the `n` option. – Gareth Oct 3 '12 at 19:03
Remove `-M5.010` and exchange `-e` for `-E` – Brad Gilbert b2gills Nov 28 '15 at 19:31

## 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.

-
+1, because anyone doing a program in GolfScript has earned it. – Gareth Oct 3 '12 at 21:37
@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. – shiona Oct 3 '12 at 22:20
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) – Peter Taylor Oct 3 '12 at 22:32
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. – Peter Taylor Oct 3 '12 at 22:34

## J, 53434139 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
``````
-

# 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"
``````
-

# 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

-

## Perl (37)

``````\$_=<>;s/^/say join',',/;s/-/../g;eval
``````
-
- when you answer, show the output for `s="1,3-5,9,16,18-23"`, thanks – BernaMariano Oct 3 '12 at 17:40
How about `say join",",eval<>=~s/-/../gr` at 29 bytes – Brad Gilbert b2gills Nov 28 '15 at 19:15

## 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...

-
Welcome to PPCG. I think you can make your answer shorter by using 1 space for indents. – intrepidcoder Nov 26 '15 at 2:42
Thanks @intrepidcoder, I didn't know that you could use single space indents. – AH L Nov 27 '15 at 1:26

## 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.

-
comma-separated output would be nicer, though i can se a 5-spaces-separated pattern, thats cool for me :) – BernaMariano Nov 27 '15 at 14:05

## Perl 6, 36 bytes

``````\$_=get;say join ',',EVAL S:g/\-/../
``````
``````1,3,4,5,9,16,18,19,20,21,22,23
``````
-

## PowerShell, 79 Bytes

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

# 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 and joins them all
# together with commas, 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
``````
-