2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,12 +1,16 @@
{{:Range extraction/Format}}
'''The task'''
;Task:
* Create a function that takes a list of integers in increasing order and returns a correctly formatted string in the range format.
* Use the function to compute and print the range formatted version of the following ordered list of integers. (The correct answer is: <code>0-2,4,6-8,11,12,14-25,27-33,35-39</code>.)
<br>
0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39
* Show the output of your program.
C.f. [[Range expansion]]
;Related task:
* &nbsp; [[Range expansion]]
<br><br>

View file

@ -0,0 +1,120 @@
on run
rangeString([0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, ¬
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, ¬
28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39])
end run
-- rangeString :: [Int] -> String
on rangeString(xs)
script addNumberOrRange
property iLast : length of xs
-- [[Int]] -> Int -> Int -> [Int] -> [[Int]]
on lambda(lstAccumulator, x, iPosn, xs)
if iPosn < iLast then
if ((item (iPosn + 1) of xs) - x) > 1 then -- rightward gap > 1
[[x]] & lstAccumulator --> start of new series
else
-- Prepended to current series
-- (if a series-breaker, or start list, is at left)
if ((iPosn = 1) or (x - (item (iPosn - 1) of xs)) > 1) then
[[x] & (item 1 of lstAccumulator)] & tail(lstAccumulator)
else
lstAccumulator -- Stet - series continues
end if
end if
else
[[x]]
end if
end lambda
end script
interCalate(",", ¬
map(my delimitedString, ¬
foldr(addNumberOrRange, [], xs)))
end rangeString
-- delimitedString :: [Int] -> String
on delimitedString(lstInt)
set intFirst to item 1 of lstInt
if length of lstInt > 1 then
set intSecond to item 2 of lstInt
set delta to intSecond - intFirst
else
set delta to 0
end if
if delta > 0 then
(intFirst as string) & cond(delta > 1, "-", ",") & intSecond as string
else
intFirst as string
end if
end delimitedString
-- GENERIC LIBRARY FUNCTIONS
-- intercalate :: Text -> [Text] -> Text
on interCalate(strText, lstText)
set {dlm, my text item delimiters} to {my text item delimiters, strText}
set strJoined to lstText as text
set my text item delimiters to dlm
return strJoined
end interCalate
-- foldr :: (a -> b -> a) -> a -> [b] -> a
on foldr(f, startValue, xs)
set mf to mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from lng to 1 by -1
set v to mf's lambda(v, item i of xs, i, xs)
end repeat
return v
end foldr
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
set mf to mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to mf's lambda(item i of xs, i, xs)
end repeat
return lst
end map
-- cond :: Bool -> (a -> b) -> (a -> b) -> (a -> b)
on cond(bool, f, g)
if bool then
f
else
g
end if
end cond
-- tail :: [a] -> [a]
on tail(xs)
if class of xs is list and length of xs > 1 then
items 2 thru -1 of xs
else
{}
end if
end tail
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property lambda : f
end script
end if
end mReturn

View file

@ -2,21 +2,21 @@ defmodule RC do
def range_extract(list) do
max = Enum.max(list) + 2
sorted = Enum.sort([max|list])
canidate_number = hd(sorted)
candidate_number = hd(sorted)
current_number = hd(sorted)
extract(tl(sorted), canidate_number, current_number, [])
extract(tl(sorted), candidate_number, current_number, [])
end
defp extract([], _, _, range), do: Enum.reverse(range) |> Enum.join(",")
defp extract([next|rest], canidate, current, range) when current+1 >= next do
extract(rest, canidate, next, range)
defp extract([next|rest], candidate, current, range) when current+1 >= next do
extract(rest, candidate, next, range)
end
defp extract([next|rest], canidate, current, range) when canidate == current do
defp extract([next|rest], candidate, current, range) when candidate == current do
extract(rest, next, next, [to_string(current)|range])
end
defp extract([next|rest], canidate, current, range) do
seperator = if canidate+1 == current, do: ",", else: "-"
str = "#{canidate}#{seperator}#{current}"
defp extract([next|rest], candidate, current, range) do
separator = if candidate+1 == current, do: ",", else: "-"
str = "#{candidate}#{separator}#{current}"
extract(rest, next, next, [str|range])
end
end

View file

@ -0,0 +1,59 @@
SUBROUTINE IRANGE(TEXT) !Identifies integer ranges in a list of integers.
Could make this a function, but then a maximum text length returned would have to be specified.
CHARACTER*(*) TEXT !The list on input, the list with ranges on output.
INTEGER LOTS !Once again, how long is a piece of string?
PARAMETER (LOTS = 666) !This should do, at least for demonstrations.
INTEGER VAL(LOTS) !The integers of the list.
INTEGER N !Count of numbers.
INTEGER I,I1 !Steppers.
N = 1 !Presume there to be one number.
DO I = 1,LEN(TEXT) !Then by noticing commas,
IF (TEXT(I:I).EQ.",") N = N + 1 !Determine how many more there are.
END DO !Step alonmg the text.
IF (N.LE.2) RETURN !One comma = two values. Boring.
IF (N.GT.LOTS) STOP "Too many values!"
READ (TEXT,*) VAL(1:N) !Get the numbers, with free-format flexibility.
TEXT = "" !Scrub the parameter!
L = 0 !No text has been placed.
I1 = 1 !Start the scan.
10 IF (L.GT.0) CALL EMIT(",") !A comma if there is prior text.
CALL SPLOT(VAL(I1)) !The first number always appears.
DO I = I1 + 1,N !Now probe ahead
IF (VAL(I - 1) + 1 .NE. VAL(I)) EXIT !While values are consecutive.
END DO !Up to the end of the remaining list.
IF (I - I1 .GT. 2) THEN !More than two consecutive values seen?
CALL EMIT("-") !Yes!
CALL SPLOT(VAL(I - 1)) !The ending number of a range.
I1 = I !Finger the first beyond the run.
ELSE !But if too few to be worth a span,
I1 = I1 + 1 !Just finger the next number.
END IF !So much for that starter.
IF (I.LE.N) GO TO 10 !Any more?
CONTAINS !Some assistants to save on repetition.
SUBROUTINE EMIT(C) !Rolls forth one character.
CHARACTER*1 C !The character.
L = L + 1 !Advance the finger.
IF (L.GT.LEN(TEXT)) STOP "Ran out of text!" !Maybe not.
TEXT(L:L) = C !And place the character.
END SUBROUTINE EMIT !That was simple.
SUBROUTINE SPLOT(N) !Rolls forth a signed number.
INTEGER N !The number.
CHARACTER*12 FIELD !Sufficient for 32-bit integers.
INTEGER I !A stepper.
WRITE (FIELD,"(I0)") N!Roll the number, with trailing spaces.
DO I = 1,12 !Now transfer the text of the number.
IF (FIELD(I:I).LE." ") EXIT !Up to the first space.
CALL EMIT(FIELD(I:I)) !One by one.
END DO !On to the end.
END SUBROUTINE SPLOT !Not so difficult either.
END !So much for IRANGE.
PROGRAM POKE
CHARACTER*(200) SOME
SOME = " 0, 1, 2, 4, 6, 7, 8, 11, 12, 14, "
1 //" 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,"
2 //"25, 27, 28, 29, 30, 31, 32, 33, 35, 36, "
3 //"37, 38, 39 "
CALL IRANGE(SOME)
WRITE (6,*) SOME
END

View file

@ -1,41 +1,22 @@
public class Range{
public static void main(String[] args){
System.out.println(compress2Range("-6, -3, -2, -1, 0, 1, 3, 4, 5, 7," +
" 8, 9, 10, 11, 14, 15, 17, 18, 19, 20"));
System.out.println(compress2Range(
"0, 1, 2, 4, 6, 7, 8, 11, 12, 14, " +
"15, 16, 17, 18, 19, 20, 21, 22, 23, 24," +
"25, 27, 28, 29, 30, 31, 32, 33, 35, 36," +
"37, 38, 39"));
}
public class RangeExtraction {
private static String compress2Range(String expanded){
StringBuilder result = new StringBuilder();
String[] nums = expanded.replace(" ", "").split(",");
int firstNum = Integer.parseInt(nums[0]);
int rangeSize = 0;
for(int i = 1; i < nums.length; i++){
int thisNum = Integer.parseInt(nums[i]);
if(thisNum - firstNum - rangeSize == 1){
rangeSize++;
}else{
if(rangeSize != 0){
result.append(firstNum).append((rangeSize == 1) ? ",": "-")
.append(firstNum+rangeSize).append(",");
rangeSize = 0;
}else{
result.append(firstNum).append(",");
}
firstNum = thisNum;
public static void main(String[] args) {
int[] arr = {0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39};
int len = arr.length;
int idx = 0, idx2 = 0;
while (idx < len) {
while (++idx2 < len && arr[idx2] - arr[idx2 - 1] == 1);
if (idx2 - idx > 2) {
System.out.printf("%s-%s,", arr[idx], arr[idx2 - 1]);
idx = idx2;
} else {
for (; idx < idx2; idx++)
System.out.printf("%s,", arr[idx]);
}
}
if(rangeSize != 0){
result.append(firstNum).append((rangeSize == 1) ? "," : "-").
append(firstNum + rangeSize);
rangeSize = 0;
} else {
result.append(firstNum);
}
return result.toString();
}
}

View file

@ -0,0 +1,45 @@
(function (lstTest) {
'use strict';
function rangeString(xs) {
var iRightmost = xs.length - 1,
// Using foldr/reduceRight proves simpler here than foldl/reduce
// (the left end of the list is easier to reach than the tip of the tail)
lstSeries = xs.reduceRight(function (a, x, i, l) {
return i < iRightmost ? (
// new series if rightward gap > 1
l[i + 1] - x > 1 ? (
[[x]].concat(a)
) : (
// This value prepended to current series (if a
// series-breaker, or the start of the list, is at left)
(i === 0 || (x - l[i - 1]) > 1) ? (
[[x].concat(a[0])].concat(a.slice(1))
// or, if the series continues to the left,
// just an unmodified copy of the accumulator
) : a
)
) : [[x]];
}, []);
return lstSeries.map(function (r) {
var lng = r.length,
d = lng > 1 ? r[1] - r[0] : 0;
return d ? r[0] + (d > 1 ? '-' : ',') + r[1] : r[0];
}).join(',');
}
return rangeString(lstTest);
})([0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39]);

View file

@ -0,0 +1 @@
"0-2,4,6-8,11,12,14-25,27-33,35-39"

View file

@ -0,0 +1,28 @@
function extractRange (rList)
local rExpr, startVal = ""
for k, v in pairs(rList) do
if rList[k + 1] == v + 1 then
if not startVal then startVal = v end
else
if startVal then
if v == startVal + 1 then
rExpr = rExpr .. startVal .. "," .. v .. ","
else
rExpr = rExpr .. startVal .. "-" .. v .. ","
end
startVal = nil
else
rExpr = rExpr .. v .. ","
end
end
end
return rExpr:sub(1, -2)
end
local intList = {
0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39
}
print(extractRange(intList))

View file

@ -1,19 +1,19 @@
/*REXX program creates a range extraction from a list of numbers (can be neg.)*/
/*REXX program creates a range extraction from a list of numbers (can be negative.) */
old=0 1 2 4 6 7 8 11 12 14 15 16 17 18 19 20 21 22 23 24 25 27 28 29 30 31 32 33 35 36 37 38 39
#=words(old) /*number of integers in the number list*/
new= /*the new list, possibly with ranges. */
do j=1 to #; x=word(old,j) /*obtain Jth number in the old list. */
new=new',' x /*append " " to " new " */
inc=1 /*start with an increment of one (1). */
do k=j+1 to #; y=word(old,k) /*get the Kth number in the number list*/
if y\=x+inc then leave /*is this number not > previous by inc?*/
inc=inc+1; g=y /*increase the range, assign G (good).*/
end /*k*/
if k-1=j | g=x+1 then iterate /*Is the range=0│1? Then keep truckin'*/
new=new'-'g; j=k-1 /*indicate a range of #s; change index*/
end /*j*/
#=words(old) /*number of integers in the number list*/
new= /*the new list, possibly with ranges. */
do j=1 to #; x=word(old,j) /*obtain Jth number in the old list. */
new=new',' x /*append " " to " new " */
inc=1 /*start with an increment of one (1). */
do k=j+1 to #; y=word(old,k) /*get the Kth number in the number list*/
if y\==x+inc then leave /*is this number not > previous by inc?*/
inc=inc+1; g=y /*increase the range, assign G (good).*/
end /*k*/
if k-1=j | g=x+1 then iterate /*Is the range=0│1? Then keep truckin'*/
new=new'-'g; j=k-1 /*indicate a range of #s; change index*/
end /*j*/
new=space(substr(new, 2), 0) /*elide leading comma, also all blanks.*/
say 'old:' old /*display the old range of numbers. */
say 'new:' new /* " " new list " " */
/*stick a fork in it, we're all done. */
new=space(substr(new, 2), 0) /*elide leading comma, also all blanks.*/
say 'old:' old /*display the old range of numbers. */
say 'new:' new /* " " new list " " */
/*stick a fork in it, we're all done. */

View file

@ -1,19 +1,19 @@
/*REXX program creates a range extraction from a list of numbers (can be neg.)*/
/*REXX program creates a range extraction from a list of numbers (can be negative.) */
old=0 1 2 4 6 7 8 11 12 14 15 16 17 18 19 20 21 22 23 24 25 27 28 29 30 31 32 33 35 36 37 38 39
#=words(old); j=0 /*number of integers in the number list*/
new= /*the new list, possibly with ranges. */
do while j<#; j=j+1; x=word(old,j) /*get the Jth number in the number list*/
new=new',' x /*append " " to " new " */
inc=1 /*start with an increment of one (1). */
do k=j+1 to #; y=word(old,k) /*get the Kth number in the number list*/
if y\=x+inc then leave /*is this number not > previous by inc?*/
inc=inc+1; g=y /*increase the range, assign G (good).*/
end /*k*/
if k-1=j | g=x+1 then iterate /*Is the range=0│1? Then keep truckin'*/
new=new'-'g; j=k-1 /*indicate a range of numbers; change J*/
end /*while*/
#=words(old); j=0 /*number of integers in the number list*/
new= /*the new list, possibly with ranges. */
do while j<#; j=j+1; x=word(old,j) /*get the Jth number in the number list*/
new=new',' x /*append " " to " new " */
inc=1 /*start with an increment of one (1). */
do k=j+1 to #; y=word(old,k) /*get the Kth number in the number list*/
if y\==x+inc then leave /*is this number not > previous by inc?*/
inc=inc+1; g=y /*increase the range, assign G (good).*/
end /*k*/
if k-1=j | g=x+1 then iterate /*Is the range=0│1? Then keep truckin'*/
new=new'-'g; j=k-1 /*indicate a range of numbers; change J*/
end /*while*/
new=space(substr(new, 2), 0) /*elide leading comma, also all blanks.*/
say 'old:' old /*display the old range of numbers. */
say 'new:' new /* " " new list " " */
/*stick a fork in it, we're all done. */
new=space(substr(new, 2), 0) /*elide leading comma, also all blanks.*/
say 'old:' old /*display the old range of numbers. */
say 'new:' new /* " " new list " " */
/*stick a fork in it, we're all done. */

View file

@ -0,0 +1,2 @@
ary = [0,1,2,4,6,7,8,11,12,14,15,16,17,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39]
puts ary.sort.slice_when{|i,j| i+1 != j}.map{|a| a.size<3 ? a : "#{a[0]}-#{a[-1]}"}.join(",")

View file

@ -0,0 +1,51 @@
use std::ops::Add;
struct RangeFinder<'a, T: 'a> {
index: usize,
length: usize,
arr: &'a [T],
}
impl<'a, T> Iterator for RangeFinder<'a, T> where T: PartialEq + Add<u8, Output=T> + Copy {
type Item = (T, Option<T>);
fn next(&mut self) -> Option<Self::Item> {
if self.index == self.length {
return None;
}
let lo = self.index;
while self.index < self.length - 1 && self.arr[self.index + 1] == self.arr[self.index] + 1 {
self.index += 1
}
let hi = self.index;
self.index += 1;
if hi - lo > 1 {
Some((self.arr[lo], Some(self.arr[hi])))
} else {
if hi - lo == 1 {
self.index -= 1
}
Some((self.arr[lo], None))
}
}
}
impl<'a, T> RangeFinder<'a, T> {
fn new(a: &'a [T]) -> Self {
RangeFinder {
index: 0,
arr: a,
length: a.len(),
}
}
}
fn main() {
let n = [0,1,2,3];
for (i, (lo, hi)) in RangeFinder::new(&n).enumerate() {
if i > 0 {print!(", ")}
print!("{}", lo);
if hi.is_some() {print!("-{}", hi.unwrap())}
}
println!("");
}

View file

@ -0,0 +1,2 @@
#![feature(zero_one)]
use std::num::One;

View file

@ -0,0 +1 @@
impl<'a, T> Iterator for RangeFinder<'a, T> where T: PartialEq + Add<u8, Output=T> + Copy {

View file

@ -0,0 +1 @@
impl<'a, T> Iterator for RangeFinder<'a, T> where T: PartialEq + Add<T, Output=T> + Copy + One {

View file

@ -0,0 +1 @@
while self.index < self.length - 1 && self.arr[self.index + 1] == self.arr[self.index] + 1 {

View file

@ -0,0 +1 @@
while self.index < self.length - 1 && self.arr[self.index + 1] == self.arr[self.index] + T::one() {

View file

@ -0,0 +1,9 @@
(defun range-extract (numbers)
`@{(mapcar [iff [callf > length (ret 2)]
(ret `@[@1 0]-@[@1 -1]`)
(ret `@{@1 ","}`)]
(mapcar (op mapcar car)
(split [window-map 1 :reflect
(op list @2 (- @2 @1))
(sort (uniq numbers))]
(op where [chain second (op < 1)])))) ","}`)