aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-115/james-smith/perl/ch-1.pl149
-rw-r--r--challenge-115/james-smith/perl/ch-2.pl149
2 files changed, 149 insertions, 149 deletions
diff --git a/challenge-115/james-smith/perl/ch-1.pl b/challenge-115/james-smith/perl/ch-1.pl
index ba5bed2831..b7ea0e4418 100644
--- a/challenge-115/james-smith/perl/ch-1.pl
+++ b/challenge-115/james-smith/perl/ch-1.pl
@@ -5,34 +5,141 @@ use strict;
use warnings;
use feature qw(say);
use Test::More;
+use Benchmark qw(cmpthese);
-my @TESTS = (
- [[qw(4 1 7 6)], 7614],
- [[qw(1 4 2 8)], 8412],
- [[qw(1 0 2 6)], 6210],
- [[qw(1 7 9 6)], 9716],
- [[qw(1 7 3 5)], ''],
- [[qw(1 7 3 8)], 7318],
- [[qw(2 4 6 8)], 8642],
+my @examples = (
+ [ [qw(abc dea cd)], 1, 1 ],
+ [ [qw(ade cbd fgh)], 0, 0 ],
+ [ [qw(ab bc ca de ef fd)], 0, 1 ],
+ [ [qw(ab bc ca ae)], 0, 1 ],
+ [ [qw(bad bed bid bod bud dub dob dib deb dab)], 1, 1 ],
+ [ [qw(abc def fed)], 0, 1 ],
+ [ [qw(ana)], 1, 1 ],
+ [ [qw(ana bob)], 0, 1 ],
+ [ [qw(ana one ant glo ten era nag )], 1, 1 ],
+ [ [qw(ana bad bed dab deb)], 0, 1 ],
+ [ [qw(bad bed ana dab deb)], 0, 1 ],
+ [ [qw(abc cde efg ghi ijk kla cpq qpc eft the ilm mli)], 1, 1 ],
+ [ [qw(pk fz iy oz cf xm gm uy ur te ct zz rw jm aq oq xy mi me rv jc iv sx pq lz nd cm vj uf rq ij zk ef wm bb cj vv oo og ft fq mj os uh gn ml mz fm az yr zh wa bm gj xn df yf er xc xb bl uw ri nq nn oi pc ym jr da rz bq vm sr ni jz po oj wf iu ja tu lk yt nc sl wi zb hm uv th kn hk pv yq ez we im gt za sj nh qr bt rr ok ai xx qs lg ue fc ws vc vy ki xi wy fv lt rl xw nj gu dz ip zl je pf hn uk di mv ug vf uz wt yn qx rh sz fh pm sa qz gp gw jp ve le fe ia nw pu km uo gy li pe hj mn ew hg qg se mq by vh ca hd bn nl xu dd ji bd ol vp wp yo st ac bh bx fa md zx mm ox qi mc lc jx wz jd xt vr yj pn uj zy ih ul pb id xh wb qq xg ou sp bo yz bu ec vz fy io hl jo cl zs ge tz qp mf zf kq sk qw as vs rm jw yk tr cw tk xz kt ra qo tj fu dy hx ic ej nt jt gf ko rd od ep qn sg ek ui bg iw zm at dv fx kb xr nu xl xs lr xk na ne xe rt jf ga hv kf xq sq pt cp rj fr fp qf gg ii ey tn ce ya kl wc ks qh em gc ts dn wk is fo pa sd ly uc zn dk wq bw tq kg xf vn ea hh ik lm nr wd kc mu ru co kx nb gl fs bi hu fk ld qa qy qm wl cn cr zd ke jl gz wr xp tm tl kj no ex wj su dc sh ee hf dw ax ms hq jj sb ed qj vw ha ju wx yi sf ln jy rx ei sy ar dm hr al ah mb on ob uq ps lv ad jk rb fb gk cc rp jq ka my ix nv re vk tp zw rg tb up pp uu ds ho zv nf ty cu kp eg in lu hy mk um zt hc qt yp tv rk hb pj ph bk af to lq qe ib gi bz jh iz lo yv ci jg gh yx bj il cz gx ro ff kk vd ub et bs tw si qd ql au ti xj yh yl kr om nx lw wo gs gq ku mw py tx ll fl xd ch rc go dt lx zu ry hz bc lj la lh ux sc fn it ir tt mo pr gd sm mx jn cd vl vb mt pz vt he eh ss dh dj yw xv be ov wh ww pg ao es ye xa vq hs yc yd vu ns zr lf rs pl cs eo zi qb qk so oc wn el zc yb de mg fw cx cv wv ot cb qu wu nm ow zp rn hw lp ma en vg cy rf tc am ut cq sv kv oh jb np us ck mh ny gr gb op an kw aa vo zq iq ba px dr un or ze bp zg eb ud if dl dq zj ky bf vi cg ua br yu mp bv sn pi db ae of kh pd hp qc jv xo du fg ta do kd dx av ys tg ls fi kz tf eu aj sw vx oa pw fd ab hi va lb dg ig dp nz js qv ag aw eq mr zo yy ie nk yg ap oe gv oy ht ev ak td ay fj ng wg)], 1, 1 ],
);
-is( biggest_even( $_->[0] ), $_->[1] ) foreach @TESTS;
+warn "SNR";
+is(circ_single_non_recursive(@{$_->[0]}),$_->[1]) foreach @examples;
+warn "S";
+is(circ_single(@{$_->[0]}),$_->[1]) foreach @examples;
+warn "A";
+is(circ_any( @{$_->[0]}),$_->[2]) foreach @examples;
-sub biggest_even {
- my $ptr = my @digits = reverse sort @{$_[0]};
+done_testing();
- ## Firstly grab the digits in reverse numerical order
- ## Keep looping backwards through the array until we
- ## find a digit which is even - if this is the case
- ## we move it to the back and return the list.
+cmpthese( 400, {
+ 1 => sub { circ_single(@{$_->[0]}) foreach @examples; },
+ 2 => sub { circ_single_non_recursive(@{$_->[0]}) foreach @examples; },
+ 0 => sub { circ_any(@{$_->[0]}) foreach @examples; },
+} );
- while( $ptr-- ) {
- next if $digits[$ptr] & 1; ## Skip if odd...
- return join '',
- @digits[ 0..$ptr-1, $ptr+1..$#digits, $ptr ];
+sub circ_single_non_recursive {
+ my @words = @_;
+ my %F;
+ ($F{substr$_,0,1}++,$F{substr$_,-1}--) foreach @words;
+ return 0 if grep {$_} values %F; ## This quickly filters out those cases in which we
+ ## can't join end on end... now there is a harder
+ ## problem coming up which is to work out if there
+ ## is a multi-loop option
+ ## Now we start at any point and get the first circle....
+ my %seen;
+ while(@words) {
+ my $init = shift @words;
+ $seen{ord $init}=1;
+ my $ptr = 0;
+ ## Skip this bit if the word is "self-closing" ie starts/ends
+ ## with same letter...
+ if( substr($init,0,1) ne substr $init, -1 ) {
+ while($ptr++ < @words) {
+ if( (substr $init,-1) eq substr $words[0],0,1 ) {
+ $seen{ ord $words[0] } = 1;
+ $init =shift @words;
+ $ptr = 0;
+ return 1 unless @words;
+ }
+ push @words, shift @words;
+ }
+ }
+ return 1 unless @words; ## We have no words left - success...
+ $ptr=0;
+ $init=undef;
+ while( $ptr++ < @words) {
+ if($seen{ord $words[0]}) {
+ $init=1;
+ last;
+ }
+ push @words,shift@words;
+ }
+ return 0 unless $init;
+ }
+ return 1;
+}
+
+sub circ_single {
+no warnings 'recursion'; ## Disable deep recursion warning - this gets messy...
+ my @words = @_;
+ my %F;
+ ($F{substr$_,0,1}++,$F{substr$_,-1}--) foreach @words;
+ return 0 if grep {$_} values %F; ## This quickly filters out those cases in which we
+ ## can't join end on end... now there is a harder
+ ## problem coming up which is to work out if there
+ ## is a multi-loop option
+ ## e.g. "ab","bc","ca","de","ef","fd" - which
+ ## can't make a single loop...
+ ## Special case where we have 1 word and it starts/ends with the same letter!
+ return 1 if @words ==1;
+
+ ## nested sub-function which does the exhaustive/recurisve search for a single
+ ## "circle"... look through all routes....
+ sub exhaust {
+ my ($init,@words) = @_;
+ my $n = @words;
+ ## If we have just two "words" then check that they form a loop.
+ if( $n==1) {
+ return substr($init,-1) eq substr($words[0],0,1)
+ && substr($init,0,1) eq substr($words[0],-1) ? 1 : 0;
+ }
+ ## o/w we loop through the list of words...
+ ## if the start of one word matches the end of the "first word"
+ ## then we "extend" the first word, and repeat recursively,
+ ## returning 1 if we eventually reach the criteria above...
+ foreach(1..$n) {
+ push @words,shift @words;
+ next unless (substr $init,-1) eq substr $words[0],0,1;
+ return 1 if exhaust( $init.$words[0], @words[1..($n-1)] );
+ }
+ ## In none match criteria we return 0...
+ return 0;
}
- ## If we get to the start return 0 as there are no even digits!
- return '';
+ return exhaust( @words );
+ use warnings 'recursion';
}
+sub circ_any {
+ my (@words) = @_;
+ my $n = @words;
+ ## If we have just two "words" then check that they form a loop.
+ ## o/w we loop through the list of words...
+ ## if the start of one word matches the end of the "first word"
+ ## then we "extend" the first word, and repeat recursively,
+ ## returning 1 if we eventually reach the criteria above...
+ foreach(1..$n) {
+ my $init = shift @words;
+ return 1 if (substr $init,-1) eq substr $init,0,1;
+ foreach(2..$n) {
+ push @words,shift@words;
+ next unless (substr $init,-1) eq substr $words[0],0,1;
+ return 1 if substr($init,0,1) eq substr($words[0],-1);
+ return 1 if circ_any( $init.$words[0], @words[1..($n-2)] );
+ }
+ push @words,$init;
+ }
+ ## In none match criteria we return 0...
+ return 0;
+}
diff --git a/challenge-115/james-smith/perl/ch-2.pl b/challenge-115/james-smith/perl/ch-2.pl
index b7ea0e4418..ba5bed2831 100644
--- a/challenge-115/james-smith/perl/ch-2.pl
+++ b/challenge-115/james-smith/perl/ch-2.pl
@@ -5,141 +5,34 @@ use strict;
use warnings;
use feature qw(say);
use Test::More;
-use Benchmark qw(cmpthese);
-my @examples = (
- [ [qw(abc dea cd)], 1, 1 ],
- [ [qw(ade cbd fgh)], 0, 0 ],
- [ [qw(ab bc ca de ef fd)], 0, 1 ],
- [ [qw(ab bc ca ae)], 0, 1 ],
- [ [qw(bad bed bid bod bud dub dob dib deb dab)], 1, 1 ],
- [ [qw(abc def fed)], 0, 1 ],
- [ [qw(ana)], 1, 1 ],
- [ [qw(ana bob)], 0, 1 ],
- [ [qw(ana one ant glo ten era nag )], 1, 1 ],
- [ [qw(ana bad bed dab deb)], 0, 1 ],
- [ [qw(bad bed ana dab deb)], 0, 1 ],
- [ [qw(abc cde efg ghi ijk kla cpq qpc eft the ilm mli)], 1, 1 ],
- [ [qw(pk fz iy oz cf xm gm uy ur te ct zz rw jm aq oq xy mi me rv jc iv sx pq lz nd cm vj uf rq ij zk ef wm bb cj vv oo og ft fq mj os uh gn ml mz fm az yr zh wa bm gj xn df yf er xc xb bl uw ri nq nn oi pc ym jr da rz bq vm sr ni jz po oj wf iu ja tu lk yt nc sl wi zb hm uv th kn hk pv yq ez we im gt za sj nh qr bt rr ok ai xx qs lg ue fc ws vc vy ki xi wy fv lt rl xw nj gu dz ip zl je pf hn uk di mv ug vf uz wt yn qx rh sz fh pm sa qz gp gw jp ve le fe ia nw pu km uo gy li pe hj mn ew hg qg se mq by vh ca hd bn nl xu dd ji bd ol vp wp yo st ac bh bx fa md zx mm ox qi mc lc jx wz jd xt vr yj pn uj zy ih ul pb id xh wb qq xg ou sp bo yz bu ec vz fy io hl jo cl zs ge tz qp mf zf kq sk qw as vs rm jw yk tr cw tk xz kt ra qo tj fu dy hx ic ej nt jt gf ko rd od ep qn sg ek ui bg iw zm at dv fx kb xr nu xl xs lr xk na ne xe rt jf ga hv kf xq sq pt cp rj fr fp qf gg ii ey tn ce ya kl wc ks qh em gc ts dn wk is fo pa sd ly uc zn dk wq bw tq kg xf vn ea hh ik lm nr wd kc mu ru co kx nb gl fs bi hu fk ld qa qy qm wl cn cr zd ke jl gz wr xp tm tl kj no ex wj su dc sh ee hf dw ax ms hq jj sb ed qj vw ha ju wx yi sf ln jy rx ei sy ar dm hr al ah mb on ob uq ps lv ad jk rb fb gk cc rp jq ka my ix nv re vk tp zw rg tb up pp uu ds ho zv nf ty cu kp eg in lu hy mk um zt hc qt yp tv rk hb pj ph bk af to lq qe ib gi bz jh iz lo yv ci jg gh yx bj il cz gx ro ff kk vd ub et bs tw si qd ql au ti xj yh yl kr om nx lw wo gs gq ku mw py tx ll fl xd ch rc go dt lx zu ry hz bc lj la lh ux sc fn it ir tt mo pr gd sm mx jn cd vl vb mt pz vt he eh ss dh dj yw xv be ov wh ww pg ao es ye xa vq hs yc yd vu ns zr lf rs pl cs eo zi qb qk so oc wn el zc yb de mg fw cx cv wv ot cb qu wu nm ow zp rn hw lp ma en vg cy rf tc am ut cq sv kv oh jb np us ck mh ny gr gb op an kw aa vo zq iq ba px dr un or ze bp zg eb ud if dl dq zj ky bf vi cg ua br yu mp bv sn pi db ae of kh pd hp qc jv xo du fg ta do kd dx av ys tg ls fi kz tf eu aj sw vx oa pw fd ab hi va lb dg ig dp nz js qv ag aw eq mr zo yy ie nk yg ap oe gv oy ht ev ak td ay fj ng wg)], 1, 1 ],
+my @TESTS = (
+ [[qw(4 1 7 6)], 7614],
+ [[qw(1 4 2 8)], 8412],
+ [[qw(1 0 2 6)], 6210],
+ [[qw(1 7 9 6)], 9716],
+ [[qw(1 7 3 5)], ''],
+ [[qw(1 7 3 8)], 7318],
+ [[qw(2 4 6 8)], 8642],
);
-warn "SNR";
-is(circ_single_non_recursive(@{$_->[0]}),$_->[1]) foreach @examples;
-warn "S";
-is(circ_single(@{$_->[0]}),$_->[1]) foreach @examples;
-warn "A";
-is(circ_any( @{$_->[0]}),$_->[2]) foreach @examples;
+is( biggest_even( $_->[0] ), $_->[1] ) foreach @TESTS;
-done_testing();
+sub biggest_even {
+ my $ptr = my @digits = reverse sort @{$_[0]};
-cmpthese( 400, {
- 1 => sub { circ_single(@{$_->[0]}) foreach @examples; },
- 2 => sub { circ_single_non_recursive(@{$_->[0]}) foreach @examples; },
- 0 => sub { circ_any(@{$_->[0]}) foreach @examples; },
-} );
+ ## Firstly grab the digits in reverse numerical order
+ ## Keep looping backwards through the array until we
+ ## find a digit which is even - if this is the case
+ ## we move it to the back and return the list.
-sub circ_single_non_recursive {
- my @words = @_;
- my %F;
- ($F{substr$_,0,1}++,$F{substr$_,-1}--) foreach @words;
- return 0 if grep {$_} values %F; ## This quickly filters out those cases in which we
- ## can't join end on end... now there is a harder
- ## problem coming up which is to work out if there
- ## is a multi-loop option
- ## Now we start at any point and get the first circle....
- my %seen;
- while(@words) {
- my $init = shift @words;
- $seen{ord $init}=1;
- my $ptr = 0;
- ## Skip this bit if the word is "self-closing" ie starts/ends
- ## with same letter...
- if( substr($init,0,1) ne substr $init, -1 ) {
- while($ptr++ < @words) {
- if( (substr $init,-1) eq substr $words[0],0,1 ) {
- $seen{ ord $words[0] } = 1;
- $init =shift @words;
- $ptr = 0;
- return 1 unless @words;
- }
- push @words, shift @words;
- }
- }
- return 1 unless @words; ## We have no words left - success...
- $ptr=0;
- $init=undef;
- while( $ptr++ < @words) {
- if($seen{ord $words[0]}) {
- $init=1;
- last;
- }
- push @words,shift@words;
- }
- return 0 unless $init;
- }
- return 1;
-}
-
-sub circ_single {
-no warnings 'recursion'; ## Disable deep recursion warning - this gets messy...
- my @words = @_;
- my %F;
- ($F{substr$_,0,1}++,$F{substr$_,-1}--) foreach @words;
- return 0 if grep {$_} values %F; ## This quickly filters out those cases in which we
- ## can't join end on end... now there is a harder
- ## problem coming up which is to work out if there
- ## is a multi-loop option
- ## e.g. "ab","bc","ca","de","ef","fd" - which
- ## can't make a single loop...
- ## Special case where we have 1 word and it starts/ends with the same letter!
- return 1 if @words ==1;
-
- ## nested sub-function which does the exhaustive/recurisve search for a single
- ## "circle"... look through all routes....
- sub exhaust {
- my ($init,@words) = @_;
- my $n = @words;
- ## If we have just two "words" then check that they form a loop.
- if( $n==1) {
- return substr($init,-1) eq substr($words[0],0,1)
- && substr($init,0,1) eq substr($words[0],-1) ? 1 : 0;
- }
- ## o/w we loop through the list of words...
- ## if the start of one word matches the end of the "first word"
- ## then we "extend" the first word, and repeat recursively,
- ## returning 1 if we eventually reach the criteria above...
- foreach(1..$n) {
- push @words,shift @words;
- next unless (substr $init,-1) eq substr $words[0],0,1;
- return 1 if exhaust( $init.$words[0], @words[1..($n-1)] );
- }
- ## In none match criteria we return 0...
- return 0;
+ while( $ptr-- ) {
+ next if $digits[$ptr] & 1; ## Skip if odd...
+ return join '',
+ @digits[ 0..$ptr-1, $ptr+1..$#digits, $ptr ];
}
- return exhaust( @words );
- use warnings 'recursion';
+ ## If we get to the start return 0 as there are no even digits!
+ return '';
}
-sub circ_any {
- my (@words) = @_;
- my $n = @words;
- ## If we have just two "words" then check that they form a loop.
- ## o/w we loop through the list of words...
- ## if the start of one word matches the end of the "first word"
- ## then we "extend" the first word, and repeat recursively,
- ## returning 1 if we eventually reach the criteria above...
- foreach(1..$n) {
- my $init = shift @words;
- return 1 if (substr $init,-1) eq substr $init,0,1;
- foreach(2..$n) {
- push @words,shift@words;
- next unless (substr $init,-1) eq substr $words[0],0,1;
- return 1 if substr($init,0,1) eq substr($words[0],-1);
- return 1 if circ_any( $init.$words[0], @words[1..($n-2)] );
- }
- push @words,$init;
- }
- ## In none match criteria we return 0...
- return 0;
-}