Range expansion: Difference between revisions

From Rosetta Code
Content added Content deleted
(!!!NOTE: FIRST RANGE CHANGED TO STOP AT NEGATIVE 1!!!)
(Mark examples needing change due to update of task. (Sorry).)
Line 10: Line 10:


=={{header|ALGOL 68}}==
=={{header|ALGOL 68}}==
{{incorrect|ALGOL 68|The task example was modified after discussion in the talk page.}}

{{works with|ALGOL 68|Revision 1 - no extensions to language used}}
{{works with|ALGOL 68|Revision 1 - no extensions to language used}}


Line 61: Line 63:


=={{header|J}}==
=={{header|J}}==
{{incorrect|J|The task example was modified after discussion in the talk page.}}


<lang j>require'strings'
<lang j>require'strings'
Line 75: Line 78:
_6 _3 _2 _1 3 4 5 7 8 9 10 11 14 15 17 18 19 20</lang>
_6 _3 _2 _1 3 4 5 7 8 9 10 11 14 15 17 18 19 20</lang>
=={{header|MUMPS}}==
=={{header|MUMPS}}==
{{incorrect|MUMPS|The task example was modified after discussion in the talk page.}}

<lang MUMPS>
<lang MUMPS>
RANGEXP(X) ;Integer range expansion
RANGEXP(X) ;Integer range expansion
Line 99: Line 104:


=={{header|OCaml}}==
=={{header|OCaml}}==
{{incorrect|OCaml|The task example was modified after discussion in the talk page.}}

<lang ocaml>#load "str.cma"
<lang ocaml>#load "str.cma"


Line 124: Line 131:


=={{header|Oz}}==
=={{header|Oz}}==
{{incorrect|Oz|The task example was modified after discussion in the talk page.}}

<lang oz>declare
<lang oz>declare
fun {Expand RangeDesc}
fun {Expand RangeDesc}
Line 185: Line 194:


=={{header|Ruby}}==
=={{header|Ruby}}==
{{incorrect|Ruby|The task example was modified after discussion in the talk page.}}

<lang ruby>def range_expand(rng)
<lang ruby>def range_expand(rng)
lst = rng.split(',').collect do |part|
lst = rng.split(',').collect do |part|
Line 207: Line 218:


=={{header|Tcl}}==
=={{header|Tcl}}==
{{incorrect|Tcl|The task example was modified after discussion in the talk page.}}

<lang tcl>proc rangeExpand desc {
<lang tcl>proc rangeExpand desc {
set result {}
set result {}

Revision as of 05:16, 17 July 2010

Task
Range expansion
You are encouraged to solve this task according to the task description, using any language you may know.

A format for expressing an ordered list of integers is to use a comma separated list of either

  • individual integers
  • Or a range of integers denoted by the starting integer separated from the end integer in the range by a dash, '-'. (The range includes all integers in the interval including both endpoints)
  • The range syntax is to be used only for, and for every range that expands to more than two values.

Example
The list of integers:

-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20

Is accurately expressed by the range expression:

-6,-3-1,3-5,7-11,14,15,17-20

(And vice-versa).

The task
Expand the range description:

-6,-3--1,3-5,7-11,14,15,17-20

Note that the second element above, is the range from minus 3 to minus 1.

C.f. Range extraction

ALGOL 68

This example is incorrect. Please fix the code and remove this message.

Details: The task example was modified after discussion in the talk page.

Works with: ALGOL 68 version Revision 1 - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny
Works with: ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release 1.8-8d

<lang algol68>MODE YIELDINT = PROC(INT)VOID;

MODE RANGE = STRUCT(INT lwb, upb); MODE RANGEINT = UNION(RANGE, INT);

OP SIZEOF = ([]RANGEINT list)INT: (

  1. determine the length of the output array #
 INT upb := LWB list - 1;
 FOR key FROM LWB list TO UPB list DO
   CASE list[key] IN
     (RANGE value): upb +:= upb OF value - lwb OF value + 1,
     (INT): upb +:= 1
   ESAC
 OD;
 upb

);

PROC gen range expand = ([]RANGEINT list, YIELDINT yield)VOID:

 FOR key FROM LWB list TO UPB list DO
   CASE list[key] IN
     (RANGE range): FOR value FROM lwb OF range TO upb OF range DO yield(value) OD,
     (INT int): yield(int)
   ESAC
 OD;

PROC range expand = ([]RANGEINT list)[]INT: (

 [LWB list: LWB list + SIZEOF list - 1]INT out;
 INT upb := LWB out - 1;
  1. FOR INT value IN # gen range expand(list, # ) DO #
    1. (INT value)VOID:
   out[upb +:= 1] := value
  1. OD #);
 out

);

test:(

 []RANGEINT list = (-6, RANGE(-3, 1), RANGE(3, 5),  RANGE(7, 11), 14, 15, RANGE(17, 20));
 print((range expand(list), new line))

)</lang> Output:

         -6         -3         -2         -1         +0         +1         +3         +4         +5         +7         +8         +9        +10        +11        +14        +15        +17        +18        +19        +20

J

This example is incorrect. Please fix the code and remove this message.

Details: The task example was modified after discussion in the talk page.

<lang j>require'strings' to=: (+ i.)/@:(0 1 + -~/\) num=: _&". normaliz=: rplc&(',-';',_';'--';'-_')@,~&',' lumps=:<@(num`([:to num;._1@,~&'-')@.('-'&e.));._1 rngexp=: ;@lumps@normaliz</lang>

Example: <lang j> rngexp '-6,-3-1,3-5,7-11,14,15,17-20' _6 _3 _2 _1 0 1 3 4 5 7 8 9 10 11 14 15 17 18 19 20

  rngexp '-6,-3--1,3-5,7-11,14,15,17-20'

_6 _3 _2 _1 3 4 5 7 8 9 10 11 14 15 17 18 19 20</lang>

MUMPS

This example is incorrect. Please fix the code and remove this message.

Details: The task example was modified after discussion in the talk page.

<lang MUMPS> RANGEXP(X) ;Integer range expansion

NEW Y,I,J,X1,H SET Y=""
FOR I=1:1:$LENGTH(X,",") DO
.S X1=$PIECE(X,",",I) FOR  Q:$EXTRACT(X1)'=" "  S X1=$EXTRACT(X1,2,$LENGTH(X1)) ;clean up leading spaces
.SET H=$FIND(X1,"-")-1
.IF H=1 SET H=$FIND(X1,"-",(H+1))-1 ;If the first value is negative ignore that "-"
.IF H<0 SET Y=$SELECT($LENGTH(Y)=0:Y_X1,1:Y_","_X1)
.IF '(H<0) FOR J=+$EXTRACT(X1,1,(H-1)):1:+$EXTRACT(X1,(H+1),$LENGTH(X1)) SET Y=$SELECT($LENGTH(Y)=0:J,1:Y_","_J)
KILL I,J,X1,H
QUIT Y</lang>

Example:

USER>SET T="-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20 "

USER>WRITE $$RANGEXP^ROSETTA(T)
-6,-3,-2,-1,0,1,3,4,5,7,8,9,10,11,14,15,17,18,19,20
USER>SET U="-10--8,"_T WRITE U
-10--8,-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20
USER>WRITE $$RANGEXP^ROSETTA(U)
-10,-9,-8,-6,-3,-2,-1,0,1,3,4,5,7,8,9,10,11,14,15,17,18,19,20

OCaml

This example is incorrect. Please fix the code and remove this message.

Details: The task example was modified after discussion in the talk page.

<lang ocaml>#load "str.cma"

let range a b =

 if b < a then invalid_arg "range";
 let rec aux i acc =
   if i = b then List.rev(i::acc)
   else aux (succ i) (i::acc)
 in
 aux a []

let parse_piece s =

 try Scanf.sscanf s "%d-%d" (fun a b -> range a b)
 with _ -> [int_of_string s]

let range_expand rng =

 let ps = Str.split (Str.regexp_string ",") rng in
 List.flatten (List.map parse_piece ps)

let () =

 let rng = "-6,-3-1,3-5,7-11,14,15,17-20" in
 let exp = range_expand rng in
 List.iter (Printf.printf " %d") exp;
 print_newline()</lang>

Oz

This example is incorrect. Please fix the code and remove this message.

Details: The task example was modified after discussion in the talk page.

<lang oz>declare

 fun {Expand RangeDesc}
    {Flatten
     {Map {ParseDesc RangeDesc}
      ExpandRange}}
 end
 fun {ParseDesc Txt}
    {Map {String.tokens Txt &,} ParseRange}
 end
 fun {ParseRange R}
    if {Member &- R.2} then
       First Second
    in
       {String.token R.2 &- ?First ?Second}
       {String.toInt R.1|First}#{String.toInt Second}
    else
       Singleton = {String.toInt R}
    in
       Singleton#Singleton
    end
 end
 fun {ExpandRange From#To}
    {List.number From To 1}
 end

in

 {Inspect {Expand "-6,-3-1,3-5,7-11,14,15,17-20"}}</lang>

Python

<lang python>def rangeexpand(txt):

   lst = []
   for r in txt.split(','):
       if '-' in r[1:]:
           r0, r1 = r[1:].split('-', 1)
           lst += range(int(r[0] + r0), int(r1) + 1)
       else:
           lst.append(int(r))
   return lst

print(rangeexpand('-6,-3--1,3-5,7-11,14,15,17-20'))</lang>

Another variant, using regular expressions to parse the ranges:

<lang python>import re

def rangeexpand(txt):

   lst = []
   for rng in txt.split(','):
       start,end = re.match('^(-?\d+)(?:-(-?\d+))?$', rng).groups()
       if end:
           lst.extend(xrange(int(start),int(end)+1))
       else:
           lst.append(int(start))
   return lst</lang>

Sample output

[-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]

Ruby

This example is incorrect. Please fix the code and remove this message.

Details: The task example was modified after discussion in the talk page.

<lang ruby>def range_expand(rng)

 lst = rng.split(',').collect do |part|
   begin
     Integer(part)
   rescue ArgumentError
     if part.scan(/^(-?\d+)-(-?\d+)$/)
       ($1.to_i .. $2.to_i).to_a
     else
       raise ArgumentError, "Can't parse part of range: '#{part}'"
     end
   end
 end
 lst.flatten

end

p range_expand('-6,-3-1,3-5,7-11,14,15,17-20')</lang>

output:

[-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]

Tcl

This example is incorrect. Please fix the code and remove this message.

Details: The task example was modified after discussion in the talk page.

<lang tcl>proc rangeExpand desc {

   set result {}
   foreach term [split $desc ","] {

set count [scan $term %d-%d from to] if {$count == 1} { lappend result $from } elseif {$count == 2} { for {set i $from} {$i <= $to} {incr i} {lappend result $i} }

   }
   return $result

}

puts [rangeExpand "-6,-3-1,3-5,7-11,14,15,17-20"]</lang> Output:

-6 -3 -2 -1 0 1 3 4 5 7 8 9 10 11 14 15 17 18 19 20