diff options
| -rwxr-xr-x | challenge-042/feng-chang/ch-1.raku | 2 | ||||
| -rwxr-xr-x | challenge-042/feng-chang/ch-2.raku | 28 | ||||
| -rwxr-xr-x | challenge-044/feng-chang/ch-1.raku | 14 | ||||
| -rwxr-xr-x | challenge-075/feng-chang/raku/ch-2.raku.local | 13 | ||||
| -rwxr-xr-x | challenge-091/feng-chang/raku/ch-1.raku | 14 | ||||
| -rwxr-xr-x | challenge-091/feng-chang/raku/ch-2.raku | 4 | ||||
| -rwxr-xr-x | challenge-093/feng-chang/ch-1.raku | 50 | ||||
| -rwxr-xr-x | challenge-093/feng-chang/ch-2.raku | 24 | ||||
| -rwxr-xr-x | challenge-094/feng-chang/ch-1.raku | 19 | ||||
| -rwxr-xr-x | challenge-094/feng-chang/ch-2.raku | 35 | ||||
| -rwxr-xr-x | challenge-096/feng-chang/ch-1.raku | 4 | ||||
| -rwxr-xr-x | challenge-096/feng-chang/ch-2.raku | 27 | ||||
| -rwxr-xr-x | challenge-101/feng-chang/raku/ch-1.raku | 61 | ||||
| -rwxr-xr-x | challenge-101/feng-chang/raku/ch-2.raku | 23 |
14 files changed, 318 insertions, 0 deletions
diff --git a/challenge-042/feng-chang/ch-1.raku b/challenge-042/feng-chang/ch-1.raku new file mode 100755 index 0000000000..83b4c4a5f6 --- /dev/null +++ b/challenge-042/feng-chang/ch-1.raku @@ -0,0 +1,2 @@ +#!/bin/env raku +(^51).map({ put "Decimal $_ = Octal { .base(8) }" }); diff --git a/challenge-042/feng-chang/ch-2.raku b/challenge-042/feng-chang/ch-2.raku new file mode 100755 index 0000000000..c5f7106d4a --- /dev/null +++ b/challenge-042/feng-chang/ch-2.raku @@ -0,0 +1,28 @@ +#!/bin/env raku + +sub is-balanced(Str:D $s --> Bool) { + my Int $i; + for $s.comb { + when '(' { ++$i } + when ')' { --$i; return False if $i < 0; } + default { return False } + } + + $i == 0; +} + +multi MAIN('test') { + use Test; + + ok is-balanced('()'), '() is good'; + ok is-balanced('(())'), '(()) is good'; + + nok is-balanced(')('), ')( is bad'; + nok is-balanced('())()'), '())() is bad'; +} + +multi MAIN(Str:D $string-of-braces) { + given $string-of-braces { + put "$_ -{ ' not' if !is-balanced($_) } ok"; + } +} diff --git a/challenge-044/feng-chang/ch-1.raku b/challenge-044/feng-chang/ch-1.raku new file mode 100755 index 0000000000..6cf53261a6 --- /dev/null +++ b/challenge-044/feng-chang/ch-1.raku @@ -0,0 +1,14 @@ +#!/bin/env raku + +use MONKEY-SEE-NO-EVAL; + +my @even = 0, 2 ... 16; +my @odd = 1, 3 ... 15; + +([X] (['', '+', '-'] xx 8)).hyper(degree => 12).map({ + my @a; + @a[@even] = '123456789'.comb; + @a[@odd] = $_; + my $s = @a.join; + put $s if EVAL($s) == 100; +}); diff --git a/challenge-075/feng-chang/raku/ch-2.raku.local b/challenge-075/feng-chang/raku/ch-2.raku.local new file mode 100755 index 0000000000..d64b758512 --- /dev/null +++ b/challenge-075/feng-chang/raku/ch-2.raku.local @@ -0,0 +1,13 @@ +#!/bin/env raku + +sub largest-rectangle-histogram(Int:D @A) { + my Int $n = @A.elems; + for 0..($n-1) -> $i { + for $i..($n-1) -> $j { + say min(|@A[$i..$j]) * ($j - $i + 1); + } + } +} + +largest-rectangle-histogram(my Int @ = 2, 1, 4, 5, 3, 7); +largest-rectangle-histogram(my Int @ = 3, 2, 3, 5, 7, 5); diff --git a/challenge-091/feng-chang/raku/ch-1.raku b/challenge-091/feng-chang/raku/ch-1.raku new file mode 100755 index 0000000000..a507ec3e5c --- /dev/null +++ b/challenge-091/feng-chang/raku/ch-1.raku @@ -0,0 +1,14 @@ +#!/bin/env raku + +sub MAIN(UInt:D $N) { + my @n = $N.comb».UInt; + + ((^@n.elems) X (^@n.elems)) # all possible ranges + .grep({ .[1] ≥ .[0] }) # end point of range should be greater or equal to start point + .grep({ [==] @n[.[0] .. .[1]] }) # all digits within the range should be the same + .grep({ .[0] == 0 or @n[.[0]-1] != @n[.[0]] }) # filter sub-ranges with left margin condition + .grep({ .[1] == @n.elems-1 or @n[.[1]] != @n[.[1]+1] }) # fliter sub-ranges with right margin condition + .map({ "{ .[1] - .[0] + 1 }{ @n[.[0]] }" }) # output each range + .join + .put; +} diff --git a/challenge-091/feng-chang/raku/ch-2.raku b/challenge-091/feng-chang/raku/ch-2.raku new file mode 100755 index 0000000000..75af8104d2 --- /dev/null +++ b/challenge-091/feng-chang/raku/ch-2.raku @@ -0,0 +1,4 @@ +#!/bin/env raku + +sub MAIN(*@N) { +} diff --git a/challenge-093/feng-chang/ch-1.raku b/challenge-093/feng-chang/ch-1.raku new file mode 100755 index 0000000000..00a375faa7 --- /dev/null +++ b/challenge-093/feng-chang/ch-1.raku @@ -0,0 +1,50 @@ +#!/bin/env raku + +grammar Dots { + rule TOP { <coord>+ % ',' } + rule coord { <[(]> <number> ** 2 % ',' <[)]> } + token number { \d+ } +} + +class DotsActions { + method TOP($/) { make $<coord>.map(*.made).Array } + method coord($/) { make $<number>.map(*.made).Array } + method number($/) { make $/.UInt } +} + +sub on-same-line(Array:D $dots -->Bool) { + $dots.elems == 2 || + ([==] $dots.map({ .[0] })) || + ([==] (1..^$dots.elems).map({ ($dots[$_;1] - $dots[0;1])/($dots[$_;0] - $dots[0;0]) })); +} + +sub max-dots(Array:D $dots -->UInt:D) { + $dots.combinations(2..$dots.elems).grep({ on-same-line($_.Array) })».elems.max; +} + +sub USAGE { + put "./ch-1.raku test\n" ~ + "./ch-1.raku '(1,1), (2,2), (3,3)'\n" ~ + "./ch-1.raku '(1,1), (2,2), (3,1), (1,3), (5,3)'" +} + +multi MAIN('test') { + use Test; + + ok on-same-line([[1, 2], [1, 3], [1, -3]]), 'the 3 points are on the same vertical line'; + ok on-same-line([[1, 1], [2, 2], [3, 3]]), 'the 3 points are on the same line'; + nok on-same-line([[1, 1], [2, 2], [3, 1]]), 'the 3 points are not on the same line'; + + is max-dots([[1,1], [2,2], [3,3]]), 3, '(1,1), (2,2), (3,3) => 3'; + is max-dots([[1,1], [2,2], [3,1], [1,3], [5,3]]), 3, '(1,1), (2,2), (3,1), (1,3), (5,3) => 3'; + + is Dots.parse('123', :rule('number'), :actions(DotsActions)).made, 123, '"123" => 123'; + is-deeply Dots.parse('(3,5)', :rule('coord'), :actions(DotsActions)).made, [3,5], '(3,5) => [3,5]'; + is-deeply Dots.parse('(3, 5)', :rule('coord'), :actions(DotsActions)).made, [3,5], '(3, 5) => [3,5]'; + + is-deeply Dots.parse('(3, 5), (1,2)', :actions(DotsActions)).made, [[3,5],[1,2]], '"(3, 5), (1,2)" => [[3,5],[1,2]]'; +} + +multi MAIN(Str:D $input) { + put max-dots(Dots.parse($input, :actions(DotsActions)).made); +} diff --git a/challenge-093/feng-chang/ch-2.raku b/challenge-093/feng-chang/ch-2.raku new file mode 100755 index 0000000000..ff099926a8 --- /dev/null +++ b/challenge-093/feng-chang/ch-2.raku @@ -0,0 +1,24 @@ +#!/bin/env raku + +sub traverse(Any:D $node, UInt:D $sum --> UInt:D) { + $node.^name ~~ 'Int' ?? + $node + $sum !! + [+] (traverse($_, $sum + $node.key) for |$node.value); +} + +multi MAIN('test') { + use Test; + + is traverse(1, 0), 1, '1 : 1'; + is traverse(1 => 2, 0), 3, '1 => 2 : 3'; + is traverse(1 => (2, 3), 0), 7, '1 => (2, 3) : 7'; +} + +my Array $T .= new( + 1 => (2 => (3, 4)), + 1 => (2 => 4, 3 => (5, 6)), +); + +multi MAIN(UInt:D \n) { + put traverse($T[n], 0); +} diff --git a/challenge-094/feng-chang/ch-1.raku b/challenge-094/feng-chang/ch-1.raku new file mode 100755 index 0000000000..db0720ab2e --- /dev/null +++ b/challenge-094/feng-chang/ch-1.raku @@ -0,0 +1,19 @@ +#!/bin/env raku + +sub USAGE { + put "$*PROGRAM 0\n" ~ + "$*PROGRAM 1\n" ~ + "$*PROGRAM opt bat saw tab pot top was\n" ~ + "$*PROGRAM x"; +} + +sub group-anagrams(@S) { + for @S».comb».sort».join.unique -> $foo { + put @S.grep(*.comb.sort.join eq $foo).join(', '); + } +} + +my @T = <opt bat saw tab pot top was>, [<x>]; +multi MAIN() { USAGE } +multi MAIN(UInt:D \n) { group-anagrams(@T[n]) } +multi MAIN(*@S) { group-anagrams(@S) } diff --git a/challenge-094/feng-chang/ch-2.raku b/challenge-094/feng-chang/ch-2.raku new file mode 100755 index 0000000000..dc6bacda24 --- /dev/null +++ b/challenge-094/feng-chang/ch-2.raku @@ -0,0 +1,35 @@ +#!/bin/env raku + +sub USAGE { + put "$*PROGRAM 0\n" ~ + "$*PROGRAM 1\n"; +} + +sub tree-to-list(Any:D $node, Array:D $a --> List:D) { + given $node { + when Int|Str { $a.push($node) } + when Pair { tree-to-list($node.key, $a); tree-to-list($node.value, $a) } + when List { tree-to-list($_, $a) for |$node } + when Hash { tree-to-list($node.keys.first, $a); tree-to-list($node.values.first, $a) } + default { die "got { $_.^name }!" } + } + (|$a); +} + +multi MAIN('test') { + use Test; + + is-deeply |tree-to-list(1, my Array $a .= new), 1, "1 : 1"; + is-deeply |tree-to-list('x', $a .= new), 'x', "x : x"; + + is tree-to-list((1 => 2), $a .= new), (1, 2), "1 => 2 : 1"; +} + +my @T = [ + { 1 => (2 => (4, 5 => (6, 7)), 3) }, + { 1 => (2 => (4, 5)) }, +]; + +multi MAIN(UInt:D \n) { + put tree-to-list(@T[n], my Array $a .= new); +} diff --git a/challenge-096/feng-chang/ch-1.raku b/challenge-096/feng-chang/ch-1.raku new file mode 100755 index 0000000000..a8271c123a --- /dev/null +++ b/challenge-096/feng-chang/ch-1.raku @@ -0,0 +1,4 @@ +#!/bin/env raku + +multi MAIN(Str:D $S) { put $S.words.reverse.join(' ') } +multi MAIN(*@S) { MAIN(@S.join(' ')) } diff --git a/challenge-096/feng-chang/ch-2.raku b/challenge-096/feng-chang/ch-2.raku new file mode 100755 index 0000000000..a84a74b7d7 --- /dev/null +++ b/challenge-096/feng-chang/ch-2.raku @@ -0,0 +1,27 @@ +#!/bin/env raku + +sub levenshtein-distance(Str:D $s, Str:D $t) { + my @S = $s.comb; my $m = @S.elems; + my @T = $t.comb; my $n = @T.elems; + + my Array @a = (0 xx ($m+1)).Array xx ($n+1); + @a[0;1..$m] = 1..$m; + @a[1..$n;0] = 1..$n; + + for ^$n -> $j { + for ^@S.elems -> $i { + my $subst-cost = @S[$i] eq @T[$j] ?? 0 !! 1; + + @a[$j+1;$i+1] = min( + @a[$j;$i+1] + 1, # deletion + @a[$j+1;$i] + 1, # insertion + @a[$j;$i] + $subst-cost # substitution + ); + } + } + + @a[$n;$m], @a.item; +} + +put levenshtein-distance('kitten', 'sitting')[0]; +put levenshtein-distance('Saturday', 'Sunday')[0]; diff --git a/challenge-101/feng-chang/raku/ch-1.raku b/challenge-101/feng-chang/raku/ch-1.raku new file mode 100755 index 0000000000..5e76ef3cef --- /dev/null +++ b/challenge-101/feng-chang/raku/ch-1.raku @@ -0,0 +1,61 @@ +#!/bin/env raku + +sub get-tight-mn(UInt:D \size --> List:D) { + (1..size X 1..size).grep({ .[0] ≤ .[1] and .[0] * .[1] == size}).min({ .[1] - .[0] }); +} + +sub tighten(*@A) { + my UInt ($h, $w) = get-tight-mn(@A.elems); + my @R; + @R[^$h;^$w] = '.' xx ∞; + my UInt ($y, $x) = ($h - 1, 0); + while @A.elems > 0 { + @R[$y;$x++] = $_ for @A.splice(0, $w); + + --$x; + --$h; + last unless $h > 0; + @R[--$y;$x] = $_ for @A.splice(0, $h); + + --$w; + last unless $w > 0; + @R[$y;--$x] = $_ for @A.splice(0, $w); + + --$h; + last unless $h > 0; + @R[++$y;$x] = $_ for @A.splice(0, $h); + + ++$x; + --$w; + } + + @R; +} + +sub show(*@A) { + my $width = @A[*;*]».chars.max; + put @A[$_]».fmt("%{ $width }s").join(' ') for ^@A.elems; +} + +multi MAIN('test') { + use Test; + + is-deeply get-tight-mn(6), (2, 3), 'get-tight-mn(6) => 2, 3'; + is-deeply get-tight-mn(5), (1, 5), 'get-tight-mn(5) => 1, 5'; + is-deeply get-tight-mn(9), (3, 3), 'get-tight-mn(9) => 3, 3'; + is-deeply get-tight-mn(24), (4, 6), 'get-tight-mn(24) => 4, 6'; + + is-deeply tighten(1, 2, 3), [[1, 2, 3],], 'tighten(1..3) is correct'; + is-deeply tighten(1..4), [[4, 3], [1, 2]], 'tighten(1..4) is correct'; + is-deeply tighten(1..9), [[7, 6, 5], [8, 9, 4], [1, 2, 3]], 'tighten(1..9) is correct'; + + done-testing; +} + +multi MAIN(UInt:D \n) { + show tighten(1..n); +} + +multi MAIN(*@A) { + show tighten(@A); +} diff --git a/challenge-101/feng-chang/raku/ch-2.raku b/challenge-101/feng-chang/raku/ch-2.raku new file mode 100755 index 0000000000..3e2823e892 --- /dev/null +++ b/challenge-101/feng-chang/raku/ch-2.raku @@ -0,0 +1,23 @@ +#!/bin/env raku + +class Point { + has Int $.x; + has Int $.y; +} + +sub area(Point:D $a, Point:D $b, Point:D $c) { + abs(($a.x * ($b.y - $c.y) + $b.x * ($c.y - $a.y) + $c.x * ($a.y - $b.y)) / 2); +} + +sub USAGE() { + say "Usage: {$*PROGRAM-NAME} <6 integers>"; +} + +multi MAIN(*@A where @A.elems == 6 && @A.all ~~ Int) { + my Point $a .= new(x => @A[0], y => @A[1]); + my Point $b .= new(x => @A[2], y => @A[3]); + my Point $c .= new(x => @A[4], y => @A[5]); + my Point $o .= new(x => 0, y => 0); + + say +(area($a, $b, $c) == area($a, $b, $o) + area($b, $c, $o) + area($c, $a, $o)); +} |
