11
\$\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. =)

\$\endgroup\$
  • 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\$ – Matt Oct 3 '12 at 17:16
  • 1
    \$\begingroup\$ Or overlapping? Does the output have to be sorted and not contain duplicates? \$\endgroup\$ – Peter Taylor Oct 3 '12 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\$ – BernaMariano Oct 3 '12 at 17:33
  • \$\begingroup\$ Does it have to be a full program, and is there a restriction on the format of the output? \$\endgroup\$ – Brad Gilbert b2gills Nov 28 '15 at 19:21
  • 1
    \$\begingroup\$ duplicate? \$\endgroup\$ – ev3commander Nov 28 '15 at 21:53

19 Answers 19

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

\$\endgroup\$
  • \$\begingroup\$ I've probably done the character counting wrong (with the command line options). Feel free to correct my counting, please \$\endgroup\$ – ardnew Oct 3 '12 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\$ – Gareth Oct 3 '12 at 19:03
  • \$\begingroup\$ Remove -M5.010 and exchange -e for -E \$\endgroup\$ – Brad Gilbert b2gills Nov 28 '15 at 19:31
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.

\$\endgroup\$
  • 2
    \$\begingroup\$ +1, because anyone doing a program in GolfScript has earned it. \$\endgroup\$ – Gareth Oct 3 '12 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\$ – shiona Oct 3 '12 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\$ – Peter Taylor Oct 3 '12 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\$ – Peter Taylor Oct 3 '12 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.

\$\endgroup\$
3
\$\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"
\$\endgroup\$
  • \$\begingroup\$ ","/:$,/{{x+!1+y-x}. 2#"J"$"-"\:x}'","\:0:0 for 43 bytes \$\endgroup\$ – streetster Jul 19 at 21:45
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.

\$\endgroup\$
2
\$\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
\$\endgroup\$
2
\$\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

\$\endgroup\$
1
\$\begingroup\$

Perl (37)

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

\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome to PPCG. I think you can make your answer shorter by using 1 space for indents. \$\endgroup\$ – intrepidcoder Nov 26 '15 at 2:42
  • \$\begingroup\$ Thanks @intrepidcoder, I didn't know that you could use single space indents. \$\endgroup\$ – Alex Nov 27 '15 at 1:26
1
\$\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.

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

Perl 6, 36 bytes

$_=get;say join ',',EVAL S:g/\-/../
1,3,4,5,9,16,18,19,20,21,22,23
\$\endgroup\$
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

\$\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
\$\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 :(

\$\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!

\$\endgroup\$
0
\$\begingroup\$

Ruby -p, 33 bytes

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

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Japt, 12 bytes

q, c@OvXr-'ò

Try it

\$\endgroup\$
  • \$\begingroup\$ Can you replace c@ with £? \$\endgroup\$ – Oliver Jul 19 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\$ – Shaggy Jul 19 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!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.