From 13809215bbd6899853b500386805feffe995bbe4 Mon Sep 17 00:00:00 2001 From: Roger Bell_West Date: Mon, 4 Apr 2022 09:49:42 +0100 Subject: Solutions for challenge #159 --- challenge-159/roger-bell-west/javascript/ch-1.js | 97 +++++++++ challenge-159/roger-bell-west/javascript/ch-2.js | 94 +++++++++ challenge-159/roger-bell-west/kotlin/ch-1.kt | 72 +++++++ challenge-159/roger-bell-west/kotlin/ch-2.kt | 94 +++++++++ challenge-159/roger-bell-west/lua/ch-1.lua | 104 +++++++++ challenge-159/roger-bell-west/lua/ch-2.lua | 97 +++++++++ challenge-159/roger-bell-west/perl/ch-1.pl | 56 +++++ challenge-159/roger-bell-west/perl/ch-2.pl | 78 +++++++ challenge-159/roger-bell-west/postscript/ch-1.ps | 256 +++++++++++++++++++++++ challenge-159/roger-bell-west/postscript/ch-2.ps | 217 +++++++++++++++++++ challenge-159/roger-bell-west/python/ch-1.py | 50 +++++ challenge-159/roger-bell-west/python/ch-2.py | 75 +++++++ challenge-159/roger-bell-west/raku/ch-1.p6 | 51 +++++ challenge-159/roger-bell-west/raku/ch-2.p6 | 74 +++++++ challenge-159/roger-bell-west/ruby/ch-1.rb | 52 +++++ challenge-159/roger-bell-west/ruby/ch-2.rb | 36 ++++ challenge-159/roger-bell-west/rust/ch-1.rs | 97 +++++++++ challenge-159/roger-bell-west/rust/ch-2.rs | 84 ++++++++ 18 files changed, 1684 insertions(+) create mode 100755 challenge-159/roger-bell-west/javascript/ch-1.js create mode 100755 challenge-159/roger-bell-west/javascript/ch-2.js create mode 100644 challenge-159/roger-bell-west/kotlin/ch-1.kt create mode 100644 challenge-159/roger-bell-west/kotlin/ch-2.kt create mode 100755 challenge-159/roger-bell-west/lua/ch-1.lua create mode 100755 challenge-159/roger-bell-west/lua/ch-2.lua create mode 100755 challenge-159/roger-bell-west/perl/ch-1.pl create mode 100755 challenge-159/roger-bell-west/perl/ch-2.pl create mode 100644 challenge-159/roger-bell-west/postscript/ch-1.ps create mode 100644 challenge-159/roger-bell-west/postscript/ch-2.ps create mode 100755 challenge-159/roger-bell-west/python/ch-1.py create mode 100755 challenge-159/roger-bell-west/python/ch-2.py create mode 100755 challenge-159/roger-bell-west/raku/ch-1.p6 create mode 100755 challenge-159/roger-bell-west/raku/ch-2.p6 create mode 100755 challenge-159/roger-bell-west/ruby/ch-1.rb create mode 100755 challenge-159/roger-bell-west/ruby/ch-2.rb create mode 100755 challenge-159/roger-bell-west/rust/ch-1.rs create mode 100755 challenge-159/roger-bell-west/rust/ch-2.rs diff --git a/challenge-159/roger-bell-west/javascript/ch-1.js b/challenge-159/roger-bell-west/javascript/ch-1.js new file mode 100755 index 0000000000..c18b03883d --- /dev/null +++ b/challenge-159/roger-bell-west/javascript/ch-1.js @@ -0,0 +1,97 @@ +#! /usr/bin/node + +function deepEqual(a,b) +{ + if( (typeof a == 'object' && a != null) && + (typeof b == 'object' && b != null) ) + { + var count = [0,0] + for( var key in a) count[0]++ + for( var key in b) count[1]++ + if( count[0]-count[1] != 0) {return false} + for( var key in a) + { + if(!(key in b) || !deepEqual(a[key],b[key])) {return false} + } + for( var key in b) + { + if(!(key in a) || !deepEqual(b[key],a[key])) {return false} + } + return true + } + else + { + return a === b + } +} + +function gcd (m0,n0) { + let m=m0 + let n=n0 + while (n != 0) { + [m,n]=[n,m % n] + } + return m +} + +function lcm (m,n) { + return m/gcd(m,n)*n +} + +function lcmseries(a0,b) { + let a=a0 + for (let i=a+1;i <= b;i++) { + a=lcm(a,i) + } + return a +} + +function farey (n) { + let l=lcmseries(2,n) + let d=new Map() + let s=[] + for (let i=1;i <= n;i++) { + let m=l/i + for (let j=0;j <= i;j++) { + let k=m*j + if (!d.has(k)) { + d.set(k,[j,i]) + s.push(k) + } + } + } + s.sort(function(a,b) { + return a-b; + }) + return s.map(i => d.get(i)) +} + +if (deepEqual(farey(5),[ + [0, 1], [1, 5], [1, 4], [1, 3], [2, 5], [1, 2], [3, 5], [2, 3], + [3, 4], [4, 5], [1, 1] +])) { + process.stdout.write("Pass") +} else { + process.stdout.write("FAIL") +} +process.stdout.write(" "); + +if (deepEqual(farey(7),[ + [0, 1], [1, 7], [1, 6], [1, 5], [1, 4], [2, 7], [1, 3], [2, 5], + [3, 7], [1, 2], [4, 7], [3, 5], [2, 3], [5, 7], [3, 4], [4, 5], + [5, 6], [6, 7], [1, 1] +])) { + process.stdout.write("Pass") +} else { + process.stdout.write("FAIL") +} +process.stdout.write(" "); + +if (deepEqual(farey(4),[ + [0, 1], [1, 4], [1, 3], [1, 2], [2, 3], [3, 4], [1, 1] +])) { + process.stdout.write("Pass") +} else { + process.stdout.write("FAIL") +} +process.stdout.write("\n"); diff --git a/challenge-159/roger-bell-west/javascript/ch-2.js b/challenge-159/roger-bell-west/javascript/ch-2.js new file mode 100755 index 0000000000..619b239213 --- /dev/null +++ b/challenge-159/roger-bell-west/javascript/ch-2.js @@ -0,0 +1,94 @@ +#! /usr/bin/node + +function genprimes(mx) { + let primesh=new Set([2,3]) + for (let i = 6; i <= mx; i += 6) { + for (let j = i-1; j <= i+1; j += 2) { + if (j <= mx) { + primesh.add(j); + } + } + } + let q=[2,3,5,7]; + let p=q.shift(); + let mr=Math.floor(Math.sqrt(mx)); + while (p <= mr) { + if (primesh.has(p)) { + let i=p*p + for (let i=p*p; i <= mx; i += p) { + primesh.delete(i); + } + } + if (q.length < 2) { + q.push(q[q.length-1]+4); + q.push(q[q.length-1]+2); + } + p=q.shift(); + } + let primes=[...primesh]; + primes.sort(function(a,b) { + return a-b; + }); + return primes; +} + +function primefactor (n) { + let f=new Map() + let m=n + for (let p of genprimes(Math.floor(Math.sqrt(n)))) { + while (m % p == 0) { + m=Math.floor(m/p) + if (f.has(p)) { + f.set(p,f.get(p)+1) + } else { + f.set(p,1) + } + if (m == 1) { + break + } + } + } + if (m > 1) { + if (f.has(m)) { + f.set(m,f.get(m)+1) + } else { + f.set(m,1) + } + } + return f +} + +function moebius (n) { + let z=0 + for (let v of primefactor(n).values()) { + if (v > 1) { + return 0 + } + z++ + } + if (z % 2 == 0) { + return 1 + } + return -1 +} + +if (moebius(5) == -1) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); + +if (moebius(10) == 1) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); + +if (moebius(20) == 0) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write("\n"); diff --git a/challenge-159/roger-bell-west/kotlin/ch-1.kt b/challenge-159/roger-bell-west/kotlin/ch-1.kt new file mode 100644 index 0000000000..362aa1c7f6 --- /dev/null +++ b/challenge-159/roger-bell-west/kotlin/ch-1.kt @@ -0,0 +1,72 @@ +import kotlin.math.* + +fun gcd(m0: Int,n0: Int): Int { + var m=m0 + var n=n0 + while (n != 0) { + val tmp=m % n + m = n + n = tmp + } + return m +} + +fun lcm(m: Int,n: Int): Int { + return m/gcd(m,n)*n +} + +fun lcmseries(s: List): Int { + return s.reduce { acc, x -> lcm(acc,x) } +} + +fun farey(n: Int): List> { + val l = lcmseries((2..n).toList()) + var d = mutableMapOf>() + var s = ArrayList() + for (i in 1..n) { + val m = l / i + for (j in 0..i) { + val k = m * j + if (!d.contains(k)) { + d[k]=Pair(j,i) + s.add(k) + } + } + } + s.sort() + return s.map {d[it]!!} +} + +fun main() { + if (farey(5) == listOf( + Pair(0, 1), Pair(1, 5), Pair(1, 4), Pair(1, 3), + Pair(2, 5), Pair(1, 2), Pair(3, 5), Pair(2, 3), + Pair(3, 4), Pair(4, 5), Pair(1, 1) + )) { + print("Pass") + } else { + print("FAIL") + } + print(" ") + if (farey(7) == listOf( + Pair(0, 1), Pair(1, 7), Pair(1, 6), Pair(1, 5), + Pair(1, 4), Pair(2, 7), Pair(1, 3), Pair(2, 5), + Pair(3, 7), Pair(1, 2), Pair(4, 7), Pair(3, 5), + Pair(2, 3), Pair(5, 7), Pair(3, 4), Pair(4, 5), + Pair(5, 6), Pair(6, 7), Pair(1, 1) + )) { + print("Pass") + } else { + print("FAIL") + } + print(" ") + if (farey(4) == listOf( + Pair(0, 1), Pair(1, 4), Pair(1, 3), Pair(1, 2), + Pair(2, 3), Pair(3, 4), Pair(1, 1) + )) { + print("Pass") + } else { + print("FAIL") + } + println("") +} diff --git a/challenge-159/roger-bell-west/kotlin/ch-2.kt b/challenge-159/roger-bell-west/kotlin/ch-2.kt new file mode 100644 index 0000000000..8cbe15e254 --- /dev/null +++ b/challenge-159/roger-bell-west/kotlin/ch-2.kt @@ -0,0 +1,94 @@ +import kotlin.math.* + +fun genprimes(mx: Int): ArrayList { + var primesh=mutableSetOf() + for (i in 2..3) { + primesh.add(i) + } + for (i in 6..mx+1 step 6) { + for (j in i-1..i+1 step 2) { + if (j <= mx) { + primesh.add(j) + } + } + } + var q=ArrayDeque(listOf(2,3,5,7)) + var p=q.removeFirst() + val mr=sqrt(mx.toDouble()).toInt() + while (p <= mr) { + if (primesh.contains(p)) { + for (i in p*p..mx step p) { + primesh.remove(i) + } + } + if (q.size < 2) { + q.add(q.last()+4) + q.add(q.last()+2) + } + p=q.removeFirst() + } + var primes=ArrayList(primesh.distinct()) + primes.sort() + return primes +} + +fun primefactor(n: Int): Map { + var f=mutableMapOf() + var m=n + for (p in genprimes(sqrt(m.toDouble()).toInt())) { + while (m % p == 0) { + m /= p + if (f.containsKey(p)) { + f[p] = f[p]!!+1 + } else { + f[p]=1 + } + } + if (m == 1) { + break + } + } + if (m > 1) { + if (f.containsKey(m)) { + f[m] = f[m]!!+1 + } else { + f[m]=1 + } + } + return f +} + +fun moebius(n: Int): Int { + var z: Int=0 + for (v in primefactor(n).values) { + if (v > 1) { + return 0 + } + z += 1 + } + if (z % 2 == 0) { + return 1 + } + return -1 +} + +fun main() { + if (moebius(5) == -1) { + print("Pass") + } else { + print("FAIL") + } + print(" ") + if (moebius(10) == 1) { + print("Pass") + } else { + print("FAIL") + } + print(" ") + if (moebius(20) == 0) { + print("Pass") + } else { + print("FAIL") + } + println("") +} diff --git a/challenge-159/roger-bell-west/lua/ch-1.lua b/challenge-159/roger-bell-west/lua/ch-1.lua new file mode 100755 index 0000000000..d10299f584 --- /dev/null +++ b/challenge-159/roger-bell-west/lua/ch-1.lua @@ -0,0 +1,104 @@ +#! /usr/bin/lua + +-- by Michael Anderson at +-- https://stackoverflow.com/questions/8722620/comparing-two-index-tables-by-index-value-in-lua +function recursive_compare(t1,t2) + -- Use usual comparison first. + if t1==t2 then return true end + -- We only support non-default behavior for tables + if (type(t1)~="table") then return false end + -- They better have the same metatables + local mt1 = getmetatable(t1) + local mt2 = getmetatable(t2) + if( not recursive_compare(mt1,mt2) ) then return false end + + -- Check each key-value pair + -- We have to do this both ways in case we miss some. + -- TODO: Could probably be smarter and not check those we've + -- already checked though! + for k1,v1 in pairs(t1) do + local v2 = t2[k1] + if( not recursive_compare(v1,v2) ) then return false end + end + for k2,v2 in pairs(t2) do + local v1 = t1[k2] + if( not recursive_compare(v1,v2) ) then return false end + end + + return true +end + +function gcd(m0,n0) + local m,n = m0,n0 + while n ~= 0 do + m,n = n,m % n + end + return m +end + +function lcm(m,n) + return m/gcd(m,n)*n +end + +function lcmseries(a,b) + local t=1 + for v = a,b do + t = lcm(t,v) + end + return t +end + +function farey(n) + local l=lcmseries(2,n) + local d={} + local s={} + for i = 1,n do + local m = l / i + for j = 0,i do + local k = m * j + if d[k] == nil then + d[k] = {j,i} + table.insert(s,k) + end + end + end + table.sort(s) + local out={} + for k,v in ipairs(s) do + table.insert(out,d[v]) + end + return out +end + +if recursive_compare(farey(5),{ + {0, 1}, {1, 5}, {1, 4}, {1, 3}, {2, 5}, + {1, 2}, {3, 5}, {2, 3}, {3, 4}, {4, 5}, + {1, 1} + }) then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if recursive_compare(farey(7),{ + {0, 1}, {1, 7}, {1, 6}, {1, 5}, {1, 4}, + {2, 7}, {1, 3}, {2, 5}, {3, 7}, {1, 2}, + {4, 7}, {3, 5}, {2, 3}, {5, 7}, {3, 4}, + {4, 5}, {5, 6}, {6, 7}, {1, 1} + }) then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if recursive_compare(farey(4),{ + {0, 1}, {1, 4}, {1, 3}, {1, 2}, {2, 3}, + {3, 4}, {1, 1} + }) then + io.write("Pass") +else + io.write("FAIL") +end +print("") diff --git a/challenge-159/roger-bell-west/lua/ch-2.lua b/challenge-159/roger-bell-west/lua/ch-2.lua new file mode 100755 index 0000000000..1e79067d53 --- /dev/null +++ b/challenge-159/roger-bell-west/lua/ch-2.lua @@ -0,0 +1,97 @@ +#! /usr/bin/lua + +function genprimes(mx) + local primesh = {} + for i = 2, 3 do + primesh[i] = true + end + for i = 6, mx, 6 do + for j = i-1, i+1, 2 do + if j <= mx then + primesh[j]=true + end + end + end + local q={2,3,5,7} + local p=table.remove(q,1) + local mr=math.floor(math.sqrt(mx)) + while p <= mr do + if primesh[p] ~= nil then + for i = p*p,mx,p do + primesh[i] = nil + end + end + if #q < 2 then + table.insert(q,q[#q]+4) + table.insert(q,q[#q]+2) + end + p=table.remove(q,1) + end + local primes = {} + for k,v in pairs(primesh) do + table.insert(primes,k) + end + table.sort(primes) + return primes +end + +function primefactor(n) + local f={} + local m=n + for k,p in pairs(genprimes(math.floor(math.sqrt(m)))) do + while m % p == 0 do + m=math.floor(m/p) + if f[p] == nil then + f[p]=1 + else + f[p] = f[p] + 1 + end + if m==1 then + break + end + end + end + if m>1 then + if f[m] == nil then + f[m]=1 + else + f[m] = f[m] + 1 + end + end + return f +end + +function moebius(n) + local z=0 + for k,v in pairs(primefactor(n)) do + if v > 1 then + return 0 + end + z = z + 1 + end + if z % 2 == 0 then + return 1 + end + return -1 +end + +if moebius(5) == -1 then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if moebius(10) == 1 then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if moebius(20) == 0 then + io.write("Pass") +else + io.write("FAIL") +end +print("") diff --git a/challenge-159/roger-bell-west/perl/ch-1.pl b/challenge-159/roger-bell-west/perl/ch-1.pl new file mode 100755 index 0000000000..e99d1d11f3 --- /dev/null +++ b/challenge-159/roger-bell-west/perl/ch-1.pl @@ -0,0 +1,56 @@ +#! /usr/bin/perl + +use strict; +use warnings; + +use Test::More tests => 3; +use List::Util qw(reduce); + +is_deeply(farey(5),[ + [0, 1], [1, 5], [1, 4], [1, 3], [2, 5], [1, 2], [3, 5], [2, 3], + [3, 4], [4, 5], [1, 1] + ],'example 1'); + +is_deeply(farey(7),[ + [0, 1], [1, 7], [1, 6], [1, 5], [1, 4], [2, 7], [1, 3], [2, 5], + [3, 7], [1, 2], [4, 7], [3, 5], [2, 3], [5, 7], [3, 4], [4, 5], + [5, 6], [6, 7], [1, 1] + ],'example 2'); + +is_deeply(farey(4),[ + [0, 1], [1, 4], [1, 3], [1, 2], [2, 3], [3, 4], [1, 1] + ],'example 3'); + +sub gcd { + my ($m,$n)=@_; + while ($n!=0) { + ($m,$n)=($n,$m % $n); + } + return $m; +} + +sub lcm { + my ($m,$n)=@_; + return $m/gcd($m,$n)*$n; +} + +sub lcmseries { + my $s=shift; + return reduce {lcm($a,$b)} @{$s}; +} + +sub farey { + my $n=shift; + my $l=lcmseries([2..$n]); + my %d; + foreach my $i (1..$n) { + my $m=$l/$i; + foreach my $j (0..$i) { + my $k=$m*$j; + unless (exists $d{$k}) { + $d{$k}=[$j,$i]; + } + } + } + return [map {$d{$_}} sort {$a <=> $b} keys %d]; +} diff --git a/challenge-159/roger-bell-west/perl/ch-2.pl b/challenge-159/roger-bell-west/perl/ch-2.pl new file mode 100755 index 0000000000..4893c02740 --- /dev/null +++ b/challenge-159/roger-bell-west/perl/ch-2.pl @@ -0,0 +1,78 @@ +#! /usr/bin/perl + +use strict; +use warnings; + +use Test::More tests => 3; + +is(moebius(5),-1,'example 1'); +is(moebius(10),1,'example 2'); +is(moebius(20),0,'example 3'); + +sub genprimes { + my $mx=shift; + my @primes; + { + my %primesh=map {$_ => 1} (2,3); + for (my $i=6;$i <= $mx+1; $i += 6) { + foreach my $j ($i-1,$i+1) { + if ($j <= $mx) { + $primesh{$j}=1; + } + } + } + my @q=(2,3,5,7); + my $p=shift @q; + my $mr=int(sqrt($mx)); + while ($p <= $mr) { + if ($primesh{$p}) { + my $i=$p*$p; + while ($i <= $mx) { + delete $primesh{$i}; + $i += $p; + } + } + if (scalar @q < 2) { + push @q,$q[-1]+4; + push @q,$q[-1]+2; + } + $p=shift @q; + } + @primes=sort {$a <=> $b} keys %primesh; + } + return \@primes; +} + +sub primefactor { + my $n=shift; + my %f; + my $m=$n; + foreach my $p (@{genprimes(int(sqrt($n)))}) { + while ($m % $p == 0) { + $f{$p}++; + $m=int($m/$p); + if ($m == 1) { + last; + } + } + } + if ($m > 1) { + $f{$m}++; + } + return \%f; +} + +sub moebius { + my $n=shift; + my $z=0; + foreach my $v (values %{primefactor($n)}) { + if ($v>1) { + return 0; + } + $z++; + } + if ($z % 2 == 0) { + return 1; + } + return -1; +} diff --git a/challenge-159/roger-bell-west/postscript/ch-1.ps b/challenge-159/roger-bell-west/postscript/ch-1.ps new file mode 100644 index 0000000000..30c9d167ab --- /dev/null +++ b/challenge-159/roger-bell-west/postscript/ch-1.ps @@ -0,0 +1,256 @@ +%!PS + +% begin library code + +/test { + /test.count test.count 1 add def + { + /test.pass test.pass 1 add def + } { + ( ) print + test.count (....) cvs print + (-fail) print + } ifelse +} bind def + +/test.start { + print (:) print + /test.pass 0 def + /test.count 0 def +} bind def + +/test.end { + ( ) print + test.count 0 gt { + (Passed ) print + test.pass (...) cvs print + (/) print + test.count (...) cvs print + ( \() print + test.pass 100 mul test.count idiv (...) cvs print + (%\)) print + (\r\n) print + } if +} bind def + +/deepeq { + 2 dict begin + /a exch def + /b exch def + a type b type eq { + a type /dicttype eq { + a length b length eq { + << + a { + pop + true + } forall + b { + pop + true + } forall + >> + true exch + { + pop + dup a exch known { + dup b exch known { + dup a exch get exch b exch get deepeq not { + pop false + } if + } { + false + } ifelse + } { + false + } ifelse + } forall + } { + false + } ifelse + } { + a type dup /arraytype eq exch /stringtype eq or { + a length b length eq { + true + 0 1 a length 1 sub { + dup a exch get exch b exch get deepeq not { + pop false + exit + } if + } for + } { + false + } ifelse + } { + a b eq + } ifelse + } ifelse + } { + false + } ifelse + end +} bind def + +/quicksort { % [ a c b ] -> [ a b c ] + 1 dict begin + /arr exch def + 0 arr length 1 sub quicksort.main + arr + end +} bind def + +/quicksort.main { % lo hi -> (null) + 3 dict begin + /hi exch def + /lo exch def + /xit false def + lo 0 lt { + /xit true def + } if + hi 0 lt { + /xit true def + } if + lo hi ge { + /xit true def + } if + xit not { + /p quicksort.partition def + lo p quicksort.main + p 1 add hi quicksort.main + } if + end +} bind def + +/quicksort.partition { + 3 dict begin + /pivot arr hi lo add 2 idiv get def + /i lo 1 sub def + /j hi 1 add def + { + { + /i i 1 add def + arr i get pivot ge { + exit + } if + } loop + { + /j j 1 sub def + arr j get pivot le { + exit + } if + } loop + i j ge { + j + exit + } if + i j quicksort.swap + } loop + end +} bind def + +/quicksort.swap { + 2 dict begin + /bi exch def + /ai exch def + arr ai get + arr bi get + arr exch ai exch put + arr exch bi exch put + end +} bind def + +/reduce { % array proc -> value + 2 dict begin + /p exch def + /a exch def + a 0 get + 1 1 a length 1 sub { + a exch get + p + } for + end +} bind def + + +/apush { % [a b] c -> [a b c] + exch + [ exch aload length 2 add -1 roll ] +} bind def + +/map { % array proc -> array + 2 dict begin + /p exch def + [ exch + { + p + } forall + ] +} bind def + +/keys { % dict -> array of dict keys + [ exch + { + pop + } forall + ] +} bind def + +% end library code + +/gcd { + { + dup + 3 1 roll + mod + dup 0 eq { + pop exit + } if + } loop +} bind def + +/lcm { + dup 3 -1 roll + dup 4 -1 roll + gcd idiv mul +} bind def + +/lcmseries { + { lcm } reduce +} bind def + +/farey { + 7 dict begin + /n exch def + /l [ 2 1 n { } for ] lcmseries def + /d n dup mul dict def + 1 1 n { + /i exch def + /m l i idiv def + 0 1 i { + /j exch def + /k m j mul def + d k known not { + d k [ j i ] put + } if + } for + } for + d keys quicksort { d exch get } map + end +} bind def + +(farey) test.start + +5 farey +[ [0 1] [1 5] [1 4] [1 3] [2 5] [1 2] [3 5] [2 3] [3 4] [4 5] [1 1] ] +deepeq test + +7 farey +[ [0 1] [1 7] [1 6] [1 5] [1 4] [2 7] [1 3] [2 5] [3 7] [1 2] [4 7] + [3 5] [2 3] [5 7] [3 4] [4 5] [5 6] [6 7] [1 1] ] +deepeq test + +4 farey +[ [0 1] [1 4] [1 3] [1 2] [2 3] [3 4] [1 1] ] +deepeq test + +test.end diff --git a/challenge-159/roger-bell-west/postscript/ch-2.ps b/challenge-159/roger-bell-west/postscript/ch-2.ps new file mode 100644 index 0000000000..bfc28ad691 --- /dev/null +++ b/challenge-159/roger-bell-west/postscript/ch-2.ps @@ -0,0 +1,217 @@ +%!PS + +% begin library code + +/test { + /test.count test.count 1 add def + { + /test.pass test.pass 1 add def + } { + ( ) print + test.count (....) cvs print + (-fail) print + } ifelse +} bind def + +/test.start { + print (:) print + /test.pass 0 def + /test.count 0 def +} bind def + +/test.end { + ( ) print + test.count 0 gt { + (Passed ) print + test.pass (...) cvs print + (/) print + test.count (...) cvs print + ( \() print + test.pass 100 mul test.count idiv (...) cvs print + (%\)) print + (\r\n) print + } if +} bind def + +/quicksort { % [ a c b ] -> [ a b c ] + 1 dict begin + /arr exch def + 0 arr length 1 sub quicksort.main + arr + end +} bind def + +/quicksort.main { % lo hi -> (null) + 3 dict begin + /hi exch def + /lo exch def + /xit false def + lo 0 lt { + /xit true def + } if + hi 0 lt { + /xit true def + } if + lo hi ge { + /xit true def + } if + xit not { + /p quicksort.partition def + lo p quicksort.main + p 1 add hi quicksort.main + } if + end +} bind def + +/quicksort.partition { + 3 dict begin + /pivot arr hi lo add 2 idiv get def + /i lo 1 sub def + /j hi 1 add def + { + { + /i i 1 add def + arr i get pivot ge { + exit + } if + } loop + { + /j j 1 sub def + arr j get pivot le { + exit + } if + } loop + i j ge { + j + exit + } if + i j quicksort.swap + } loop + end +} bind def + +/quicksort.swap { + 2 dict begin + /bi exch def + /ai exch def + arr ai get + arr bi get + arr exch ai exch put + arr exch bi exch put + end +} bind def + +/apush { % [a b] c -> [a b c] + exch + [ exch aload length 2 add -1 roll ] +} bind def + +/values { % dict -> array of dict values + [ exch + { + exch pop + } forall + ] +} bind def + +% end library code + +/genprimes { + /mx exch def + /primesh mx dict def + 2 1 3 { + primesh exch true put + } for + 6 6 mx 1 add { + dup 1 sub exch 1 add 2 exch { + dup mx le { + primesh exch true put + } { + pop + } ifelse + } for + } for + /q [ 3 5 7 ] def + /qi 0 def + /p 2 def + /mr mx sqrt cvi def + { + p mr le not { + exit + } if + primesh p known { + p dup mul p mx { + primesh exch undef + } for + } if + q length qi sub 2 le { + /q q q q length 1 sub get 4 add apush def + /q q q q length 1 sub get 2 add apush def + } if + /p q qi get def + /qi qi 1 add def + } loop + [ primesh { pop } forall ] quicksort +} bind def + +/primefactor { + 4 dict begin + /n exch def + /f 1 dict def + /m n def + n sqrt cvi genprimes { + /p exch def + { + m p mod 0 eq { + f p known { + f p f p get 1 add put + } { + f p 1 put + } ifelse + /m m p idiv def + } { + exit + } ifelse + } loop + m 1 eq { + exit + } + } forall + m 1 gt { + f m known { + f m f m get 1 add put + } { + f m 1 put + } ifelse + } if + f + end +} bind def + +/moebius { + 1 dict begin + /z 0 def + primefactor values { + 1 gt { + /z 0 def + exit + } if + /z z 1 add def + } forall + z 0 eq { + 0 + } { + z 2 mod 0 eq { + 1 + } { + -1 + } ifelse + } ifelse + end +} bind def + +(moebius) test.start +5 moebius -1 eq test +10 moebius 1 eq test +20 moebius 0 eq test +test.end diff --git a/challenge-159/roger-bell-west/python/ch-1.py b/challenge-159/roger-bell-west/python/ch-1.py new file mode 100755 index 0000000000..d6e05acf97 --- /dev/null +++ b/challenge-159/roger-bell-west/python/ch-1.py @@ -0,0 +1,50 @@ +#! /usr/bin/python3 + +import unittest + +from math import gcd +from functools import reduce + +def lcm(m,n): + return m//gcd(m,n)*n + +def lcmseries(s): + return reduce(lcm, s) + +def farey(n): + l=lcmseries(range(2,n+1)) + d=dict() + s=[] + for i in range(1,n+1): + m=l // i + for j in range(0,i+1): + k=m*j + if not k in d: + d[k]=[j,i] + s.append(k) + s.sort() + return [d[i] for i in s] + +class TestFarey(unittest.TestCase): + + def test_ex1(self): + self.assertEqual(farey(5), + [[0,1], [1,5], [1,4], [1,3], [2,5], [1,2], + [3,5], [2,3], [3,4], [4,5], [1,1]], + 'example 1') + + def test_ex2(self): + self.assertEqual(farey(7), + [[0,1], [1,7], [1,6], [1,5], [1,4], [2,7], + [1,3], [2,5], [3,7], [1,2], [4,7], [3,5], + [2,3], [5,7], [3,4], [4,5], [5,6], [6,7], + [1,1]], + 'example 2') + + def test_ex3(self): + self.assertEqual(farey(4), + [[0,1], [1,4], [1,3], [1,2], [2,3], [3,4], + [1,1]], + 'example 3') + +unittest.main() diff --git a/challenge-159/roger-bell-west/python/ch-2.py b/challenge-159/roger-bell-west/python/ch-2.py new file mode 100755 index 0000000000..125eed5e55 --- /dev/null +++ b/challenge-159/roger-bell-west/python/ch-2.py @@ -0,0 +1,75 @@ +#! /usr/bin/python3 + +import unittest + +from math import sqrt,floor,gcd +from collections import deque + +def genprimes(mx): + primesh=set(range(2,4)) + for i in range(6,mx+2,6): + for j in range(i-1,i+2,2): + if j <= mx: + primesh.add(j) + q=deque([2,3,5,7]) + p=q.popleft() + mr=floor(sqrt(mx)) + while p <= mr: + if p in primesh: + for i in range(p*p,mx+1,p): + primesh.discard(i) + if len(q) < 2: + q.append(q[-1]+4) + q.append(q[-1]+2) + p=q.popleft() + primes=list(primesh) + primes.sort() + return primes + +def primefactor(n): + f=dict() + m=n + for p in genprimes(floor(sqrt(n))): + while (m % p == 0): + m //= p + if p in f: + f[p] += 1 + else: + f[p] = 1 + if m==1: + break + if m > 1: + if m in f: + f[m] += 1 + else: + f[m] = 1 + return f + +def moebius(n): + z=0 + for k,v in primefactor(n).items(): + if v > 1: + return 0 + z += 1 + if z % 2 == 0: + return 1 + return -1 + +class TestMoebius(unittest.TestCase): + + def test_ex1(self): + self.assertEqual(moebius(5), + -1, + 'example 1') + + def test_ex2(self): + self.assertEqual(moebius(10), + 1, + 'example 2') + + def test_ex3(self): + self.assertEqual(moebius(20), + 0, + 'example 3') + +unittest.main() diff --git a/challenge-159/roger-bell-west/raku/ch-1.p6 b/challenge-159/roger-bell-west/raku/ch-1.p6 new file mode 100755 index 0000000000..0c3dee4698 --- /dev/null +++ b/challenge-159/roger-bell-west/raku/ch-1.p6 @@ -0,0 +1,51 @@ +#! /usr/bin/perl6 + +use Test; + +plan 3; + +is-deeply(farey(5),( + 0 => 1, 1 => 5, 1 => 4, 1 => 3, 2 => 5, 1 => 2, 3 => 5, + 2 => 3, 3 => 4, 4 => 5, 1 => 1 + ),'example 1'); + +is-deeply(farey(7),( + 0 => 1, 1 => 7, 1 => 6, 1 => 5, 1 => 4, 2 => 7, 1 => 3, + 2 => 5, 3 => 7, 1 => 2, 4 => 7, 3 => 5, 2 => 3, 5 => 7, + 3 => 4, 4 => 5, 5 => 6, 6 => 7, 1 => 1 + ),'example 2'); + +is-deeply(farey(4),( + 0 => 1, 1 => 4, 1 => 3, 1 => 2, 2 => 3, 3 => 4, 1 => 1 + ),'example 3'); + +sub gcd($m0,$n0) { + my ($m,$n)=($m0,$n0); + while ($n != 0) { + ($m,$n)=($n,$m % $n); + } + return $m; +} + +sub lcm($m,$n) { + return $m/gcd($m,$n)*$n; +} + +sub lcmseries(@s) { + return floor(@s.reduce(&lcm)); +} + +sub farey($n) { + my $l=lcmseries([2..$n]); + my %d; + for (1..$n) -> $i { + my $m = $l div $i; + for (0..$i) -> $j { + my $k = $m * $j; + unless (%d{$k}:exists) { + %d{$k}=Pair.new($j,$i); + } + } + } + return map {%d{$_}}, sort { $^a <=> $^b }, %d.keys; +} diff --git a/challenge-159/roger-bell-west/raku/ch-2.p6 b/challenge-159/roger-bell-west/raku/ch-2.p6 new file mode 100755 index 0000000000..79211760a0 --- /dev/null +++ b/challenge-159/roger-bell-west/raku/ch-2.p6 @@ -0,0 +1,74 @@ +#! /usr/bin/perl6 + +use Test; + +plan 3; + +is(moebius(5),-1,'example 1'); +is(moebius(10),1,'example 2'); +is(moebius(20),0,'example 3'); + +sub genprimes($mx) { + my @primes; + { + my $primesh=(2,3).SetHash; + loop (my $i=6;$i <= $mx+1; $i += 6) { + for ($i-1,$i+1) -> $j { + if ($j <= $mx) { + $primesh{$j}=True; + } + } + } + my $p=2; + my @q=[2,3,5,7]; + my $mr=floor(sqrt($mx)); + while ($p <= $mr) { + if ($primesh{$p}:exists) { + my $i=$p*$p; + while ($i <= $mx) { + $primesh{$i}:delete; + $i += $p; + } + } + if (@q.elems < 2) { + @q.push(@q[*-1]+4); + @q.push(@q[*-1]+2); + } + $p=@q.shift; + } + @primes=$primesh.keys.sort; + } + return @primes; +} + +sub primefactor($n) { + my %f; + my $m=$n; + for genprimes(floor(sqrt($n))) -> $p { + while ($m % $p == 0) { + %f{$p}++; + $m=floor($m/$p); + } + if ($m == 1) { + last; + } + } + if ($m > 1) { + %f{$m}++; + } + return %f; +} + +sub moebius($n) { + my $z=0; + for primefactor($n).values -> $v { + if ($v > 1) { + return 0; + } + $z++; + } + if ($z % 2 == 0) { + return 1; + } + return -1; +} diff --git a/challenge-159/roger-bell-west/ruby/ch-1.rb b/challenge-159/roger-bell-west/ruby/ch-1.rb new file mode 100755 index 0000000000..593a5ac426 --- /dev/null +++ b/challenge-159/roger-bell-west/ruby/ch-1.rb @@ -0,0 +1,52 @@ +#! /usr/bin/ruby + +require 'test/unit' + +require 'set' +require 'prime' + +def lcmseries(s) + return s.inject {|a, b| a.lcm(b)} +end + +def farey(n) + l=lcmseries(2.upto(n)) + d={} + s=[] + 1.upto(n) do |i| + m = l / i + 0.upto(i) do |j| + k = m * j + if !d.has_key?(k) then + d[k]=[j,i] + s.push(k) + end + end + end + s.sort! + return s.map{|i| d[i]} +end + +class TestFarey < Test::Unit::TestCase + + def test_ex1 + assert_equal([[0, 1], [1, 5], [1, 4], [1, 3], [2, 5], [1, 2], + [3, 5], [2, 3], [3, 4], [4, 5], [1, 1]], + farey(5)) + end + + def test_ex2 + assert_equal([[0, 1], [1, 7], [1, 6], [1, 5], [1, 4], [2, 7], + [1, 3], [2, 5], [3, 7], [1, 2], [4, 7], [3, 5], + [2, 3], [5, 7], [3, 4], [4, 5], [5, 6], [6, 7], + [1, 1]], + farey(7)) + end + + def test_ex3 + assert_equal([[0, 1], [1, 4], [1, 3], [1, 2], [2, 3], [3, 4], + [1, 1]], + farey(4)) + end + +end diff --git a/challenge-159/roger-bell-west/ruby/ch-2.rb b/challenge-159/roger-bell-west/ruby/ch-2.rb new file mode 100755 index 0000000000..4d59457cba --- /dev/null +++ b/challenge-159/roger-bell-west/ruby/ch-2.rb @@ -0,0 +1,36 @@ +#! /usr/bin/ruby + +require 'test/unit' + +require 'set' +require 'prime' + +def moebius(n) + z=0 + for vv in n.prime_division do + if vv[1] > 1 then + return 0 + end + z += 1 + end + if z % 2 == 0 then + return 1 + end + return -1 +end + +class TestMoebius < Test::Unit::TestCase + + def test_ex1 + assert_equal(-1,moebius(5)) + end + + def test_ex2 + assert_equal(1,moebius(10)) + end + + def test_ex3 + assert_equal(0,moebius(20)) + end + +end diff --git a/challenge-159/roger-bell-west/rust/ch-1.rs b/challenge-159/roger-bell-west/rust/ch-1.rs new file mode 100755 index 0000000000..aee5bc331d --- /dev/null +++ b/challenge-159/roger-bell-west/rust/ch-1.rs @@ -0,0 +1,97 @@ +#! /bin/sh +//usr/bin/env rustc --test $0 -o ${0}x && ./${0}x --nocapture; rm -f ${0}x ; exit + +use std::collections::HashMap; + +#[test] +fn test_ex1() { + assert_eq!( + farey(5), + vec![ + [0, 1], + [1, 5], + [1, 4], + [1, 3], + [2, 5], + [1, 2], + [3, 5], + [2, 3], + [3, 4], + [4, 5], + [1, 1] + ] + ); +} + +#[test] +fn test_ex2() { + assert_eq!( + farey(7), + vec![ + [0, 1], + [1, 7], + [1, 6], + [1, 5], + [1, 4], + [2, 7], + [1, 3], + [2, 5], + [3, 7], + [1, 2], + [4, 7], + [3, 5], + [2, 3], + [5, 7], + [3, 4], + [4, 5], + [5, 6], + [6, 7], + [1, 1] + ] + ); +} + +#[test] +fn test_ex3() { + assert_eq!( + farey(4), + vec![[0, 1], [1, 4], [1, 3], [1, 2], [2, 3], [3, 4], [1, 1]] + ); +} + +fn gcd(m0: usize, n0: usize) -> usize { + let mut m = m0; + let mut n = n0; + while n != 0 { + let t = n; + n = m % n; + m = t; + } + m +} + +fn lcm(m: usize, n: usize) -> usize { + m / gcd(m, n) * n +} + +fn lcmseries(s: Vec) -> usize { + s.iter().fold(1, |acc, x| lcm(acc, *x)) +} + +fn farey(n: usize) -> Vec<[usize; 2]> { + let l = lcmseries((2..=n).collect::>()); + let mut d: HashMap = HashMap::new(); + let mut s = Vec::new(); + for i in 1..=n { + let m = l / i; + for j in 0..=i { + let k = m * j; + if !d.contains_key(&k) { + d.insert(k, [j, i]); + s.push(k); + } + } + } + s.sort(); + return s.iter().map(|i| d[i]).collect::>(); +} diff --git a/challenge-159/roger-bell-west/rust/ch-2.rs b/challenge-159/roger-bell-west/rust/ch-2.rs new file mode 100755 index 0000000000..106b67293d --- /dev/null +++ b/challenge-159/roger-bell-west/rust/ch-2.rs @@ -0,0 +1,84 @@ +#! /bin/sh +//usr/bin/env rustc --test $0 -o ${0}x && ./${0}x --nocapture; rm -f ${0}x ; exit + +use std::collections::{HashMap, HashSet, VecDeque}; +use std::iter::FromIterator; + +#[test] +fn test_ex1() { + assert_eq!(moebius(5), -1); +} + +#[test] +fn test_ex2() { + assert_eq!(moebius(10), 1); +} + +#[test] +fn test_ex3() { + assert_eq!(moebius(20), 0); +} + +fn genprimes(mx: usize) -> Vec { + let mut primesh: HashSet = HashSet::from_iter(2..=3); + for i in (6..=mx).step_by(6) { + for j in [i - 1, i + 1] { + if j < mx { + primesh.insert(j); + } + } + } + let mut q = VecDeque::from([2, 3, 5, 7]); + let mut p = q.pop_front().unwrap(); + let mr = (mx as f64).sqrt() as usize; + while p <= mr { + if primesh.contains(&p) { + for i in (p * p..=mx).step_by(p as usize) { + primesh.remove(&i); + } + } + if q.len() < 2 { + let t = q[0] + 4; + q.push_back(t); + q.push_back(t + 2); + } + p = q.pop_front().unwrap(); + } + let mut primes = primesh.iter().map(|i| *i).collect::>(); + primes.sort(); + primes +} + +fn primefactor(n: usize) -> HashMap { + let mut f: HashMap = HashMap::new(); + let mut m = n; + for p in genprimes((n as f64).sqrt() as usize).iter() { + while m % p == 0 { + m /= p; + let en = f.entry(*p).or_insert(0); + *en += 1; + } + if m == 1 { + break; + } + } + if m > 1 { + let en = f.entry(m).or_insert(0); + *en += 1; + } + f +} + +fn moebius(n: usize) -> isize { + let mut z=0; + for v in primefactor(n).values() { + if *v > 1 { + return 0; + } + z += 1; + } + if z % 2 == 0 { + return 1; + } + -1 +} -- cgit