aboutsummaryrefslogtreecommitdiff
path: root/challenge-071
diff options
context:
space:
mode:
authorMyoungjin JEON <jeongoon@gmail.com>2020-08-02 02:12:33 +1000
committerMyoungjin JEON <jeongoon@gmail.com>2020-08-02 02:12:33 +1000
commita63a9ebea520836f1783689454064ad0ced584fd (patch)
tree70ee4c049849226fe4ce80b376c23795aeecd183 /challenge-071
parent3dee8e8787d5b0285bdd87968c0a5a14cacbf6af (diff)
downloadperlweeklychallenge-club-a63a9ebea520836f1783689454064ad0ced584fd.tar.gz
perlweeklychallenge-club-a63a9ebea520836f1783689454064ad0ced584fd.tar.bz2
perlweeklychallenge-club-a63a9ebea520836f1783689454064ad0ced584fd.zip
challenge #71 by Jeon
Diffstat (limited to 'challenge-071')
-rw-r--r--challenge-071/jeongoon/perl/ch-1.pl153
-rw-r--r--challenge-071/jeongoon/perl/ch-2.pl322
-rw-r--r--challenge-071/jeongoon/raku/ch-1.raku67
-rw-r--r--challenge-071/jeongoon/raku/ch-2.raku115
4 files changed, 657 insertions, 0 deletions
diff --git a/challenge-071/jeongoon/perl/ch-1.pl b/challenge-071/jeongoon/perl/ch-1.pl
new file mode 100644
index 0000000000..5108f945e9
--- /dev/null
+++ b/challenge-071/jeongoon/perl/ch-1.pl
@@ -0,0 +1,153 @@
+#!/usr/bin/env perl
+# -*- Mode: cperl; cperl-indent-level:4 tab-width: 8; indent-tabs-mode: nil -*-
+# -*- coding: utf-8 -*-
+
+use utf8;
+use strict; use warnings;
+use Getopt::Long qw(:config no_ignore_case gnu_compat);
+use Pod::Usage;
+use Term::ANSIColor;
+
+
+BEGIN {
+ $::debugging = 0;
+ $::utf8 = 1;
+ $::colour = 1;
+ $::help = 0;
+
+ GetOptions( 'debug' => \$::debugging,
+ 'utf8!' => \$::utf8,
+ 'color|colour!' => \$::colour,
+ 'N=i' => \$::N,
+ 'help' => \$::help,
+ ) or pod2usage(2);
+
+ our $dbuff_ = '';
+ our $dprint = sub ( @ ) { ++$|; print STDERR @_; };
+ our $dpush = sub ( @ ) { $dbuff_ .= join "", @_; };
+
+ if ( $::utf8 ) {
+ binmode( STDERR, ':utf8' );
+ binmode( STDOUT, ':utf8' );
+ *IC = sub { 'β†—' }; *DC = sub { 'β†˜' }; }
+ else {
+ *IC = sub { '/' }; *DC = sub { '\\' }; }
+
+ *::dpush = $::debugging ? $dpush : sub {};
+ *::dmesg = $::debugging ?
+ sub { $dprint->('[DBG] ',$dbuff_,@_ ); $dbuff_='';} : sub {};
+
+}
+
+=pod
+
+=head1 Peak Element
+
+ch-1.pl [--debug] [--help] [--no-utf8] [--no-color] [N (default: 42)]
+where 1 < N <= 50
+
+=head1 Challenge
+
+You are given positive integer $N (>1).
+
+Write a script to create an array of size $N with random unique elements between 1 and 50.
+
+ | I'm going to make a list and shuffle (because the list would be not very long.)
+ | then return @array[ 0..$N ]
+
+=cut
+
+sub make_random_array_ ( @ ) { # note: this function does not validate parameters
+ my %args = @_;
+ my $narray = $args{'number-of-array'};
+ my $members =$args{'elements'};
+
+ my $n = scalar @$members;
+
+ for ( 0.. $n*2 ) { # shuffle enough
+ my ( $l, $r ) = ( int(rand($n)), int(rand($n)) );
+ @{$members}[$l, $r] = @{$members}[$r, $l];
+ }
+ @{$members}[ 0.. $narray-1 ];
+}
+
+=pod
+
+=encoding utf8
+
+In the end it should print peak elements in the array, if found.
+
+ An array element is called peak if it is bigger than it’s neighbour.
+
+ Example 1
+ Array: [ 18, 45, 38, 25, 10, 7, 21, 6, 28, 48 ]
+ Peak: [ 48, 45, 21 ]
+ Example 2
+ Array: [ 47, 11, 32, 8, 1, 9, 39, 14, 36, 23 ]
+ Peak: [ 47, 32, 39, 36 ]
+
+=cut
+
+sub get_peak_from_array ( @ ) {
+ my $n = 0;
+ my $l = 1;
+ my $pasc = 1; # previous ascend value
+ my @ps;
+
+ ::dpush "visual list: ";
+ for (@_) {
+
+=pod
+
+=head1 My solution
+
+ | So.. I just simply compare current number to next one. if the number increased
+ | previouly and will be decreased, which means current number is peak
+
+=cut
+
+ my $d = ( ( $_[$n+1] || 0 ) - $_[$n++] ); # (d)elta
+ $d /= abs $d; # need direction only
+ my $asc = (0,1,0)[$d]; # d == 1 -> $asc = 0, $t == -1 -> $asc = 1;
+ ::dpush $pasc?IC:DC;
+
+ # I found the bit operation is interesting
+ # change comparison method a little bit.
+ # pasc asc peak
+ # 0 0 no (keep decreasing)
+ # 1 0 yes
+ # 0 1 no (low peak)
+ # 1 1 no (keep increasing)
+ # not very usueful here but I hope someday it will be :-]
+ if ( ($pasc<<1 | $asc) == 0b10 ) { # if $pasc and not $asc;
+ push @ps, $_;
+ ::dpush " ", colored( ['yellow on_black'], $_ ), " ";
+ }
+ else {
+ ::dpush " $_ ";
+ }
+ $pasc = $asc;
+ }
+ ::dmesg " ", ($pasc?IC:DC), "\n";
+ return @ps;
+}
+
+
+package main;
+
+defined $::N or
+ $::N = 42, warn "Use Default N: 42";
+
+die "Invalid value of N($::N): must be 1 < N <= 50"
+ unless $::N > 1 and $::N <= 50;
+
+pod2usage( -exitval => 0, -verbose => 2 ) if $::help;
+
+my @r_array = make_random_array_( 'number-of-array' => $::N,
+ 'elements' => [ 1..50 ] );
+$"=", ";
+
+print "Array: [ @r_array ]\n";
+print "Peak: [ ".join($", get_peak_from_array @r_array)." ]";
+
+exit 0;
diff --git a/challenge-071/jeongoon/perl/ch-2.pl b/challenge-071/jeongoon/perl/ch-2.pl
new file mode 100644
index 0000000000..d5ca392f74
--- /dev/null
+++ b/challenge-071/jeongoon/perl/ch-2.pl
@@ -0,0 +1,322 @@
+#!/usr/bin/env perl
+# -*- Mode: cperl; cperl-indent-level:4 tab-width: 8; indent-tabs-mode: nil -*-
+# -*- coding: utf-8 -*-
+
+use strict; use warnings;
+use Getopt::Long;
+use Pod::Usage;
+use Term::ANSIColor;
+
+=pod
+
+=head1 Usage
+
+perl ch-1.pl [--debug] [--help]
+
+=cut
+
+BEGIN {
+ $::debugging = 0;
+ $::colour = 1;
+ my $help = 0;
+
+ GetOptions( "debug" => \$::debugging,
+ 'color|colour!' => \$::colour,
+ "help" => \$help,
+ ) or pod2usage(2);
+
+ pod2usage( -exitval => 0, -verbose => 2 ) if $help;
+
+ our $dprint = sub( @ ) {
+ ++$|;
+ print "[DBG] ",@_;
+ };
+
+ *::dprint = $::debugging ? $dprint : sub {};
+}
+
+=pod
+
+=head1 Challenge 2
+
+You are given a singly linked list and a positive integer $N (>0).
+
+Write a script to remove the $Nth node from the end of the linked list and
+print the linked list.
+
+=cut
+
+package linked_list;
+use Scalar::Util qw(blessed refaddr weaken);
+
+sub new {
+ my $class = shift;
+ my %args = @_; # use hash as arguments
+ my $elements;
+ ::dprint "linked_list: initializing ...\n";
+ if ( exists $args{elements} ) {
+ if ( not ref $args{elements} eq 'ARRAY' ) {
+ warn "parameter elements accept only Array Ref: ignored.";
+ }
+ else {
+ $elements = $args{elements};
+ }
+
+ }
+
+ my $obj =
+ [
+ linked_list::iterator->new( '[CORE]' ) # one default iterator for internal use
+ ];
+ my $self = bless $obj, ( blessed $class || $class );
+
+ if ( defined $elements ) {
+ for ( reverse @$elements ) { # going to use unshift method
+ $self->push_back( $self->[0], $_ );
+ }
+ }
+ ::dprint "linked_list: created\n";
+ return $self;
+}
+
+sub DESTROY {
+ ::dprint "linked_list: remvoing CORE and cache.\n";
+ undef $_[0]->[0];
+ ::dprint "linked_list: done";
+}
+
+sub before_begin_ { $_[0]->[0] }
+sub begin { $_[0]->[0]->next }
+sub maybe_end { $_[0]->[1] }
+sub end {
+ # using remembered end point if any
+ $_[0]->[1] = $_[0]->[0]->next unless defined $_[0]->maybe_end;
+ # update end point if needed
+ while ( $_[0]->[1]->next ) {
+ $_[0]->[1] = $_[0]->[1]->next
+ }
+ return $_[0]->[1];
+}
+
+sub count {
+ my $itr = $_[0]->begin;
+
+ my $count = 0;
+ while ( defined $itr ) {
+ ++$count;
+ $itr = $itr->next;
+ }
+ $count;
+}
+
+sub itr_class_str () { __PACKAGE__.'::iterator' }
+
+sub push_back ( $;$ ) {
+ if ( scalar @_ == 1 ) {
+ ::dprint "nothing to do";
+ return 0;
+ }
+
+ my ( $itr, $sth ) = @_[ -2, -1 ];
+ my $class = blessed $itr;
+
+ # get valid iterator to push back
+ if ( not defined $itr ) {
+ # making begin and push something
+ ::dprint "push_back: iterator not defined: making first node";
+ return $_[0]->push_back( itr_class_str->new(), $sth );
+ }
+ if ( $class eq __PACKAGE__ ) { # scalar @_ == 2
+ ::dprint "push_back: use tail node to push $sth";
+ $itr = $_[0]->end;
+ }
+
+ # get valid iterator to be pushed back
+ $class = blessed $sth;
+ if ( $class and $class eq itr_class_str ) {
+ ::dprint "push_back: received an itr with value: ".$sth->value.$/;
+ ::dprint " to be pushed after iter with value: ".$itr->value.$/;
+ my $nxt = $itr->next;
+ $itr->[1] = $sth;
+ if ( defined $sth->next ) {
+ warn "push_back: trying to insert some node which already has link";
+ }
+ else {
+ # XXX: not sure it is correct behaviour
+ $sth->[1] = $nxt;
+ }
+ return 1;
+ }
+ else { # value
+ ::dprint "push_back: received a value: $sth\n";
+ return $_[0]->push_back( $itr, itr_class_str->new( $sth ) );
+ }
+ die "this is a bug" if $::debugging;
+}
+
+sub pop ( $;$ ) {
+ return if scalar @_ == 1;
+
+ my $class = blessed $_[-1];
+
+ if ( defined $class and $class eq __PACKAGE__ ) {
+ # pop the end
+ return $_[0]->pop( $_[0]->count - 1 );
+ }
+ if ( defined $class and $class eq itr_class_str ) {
+ ::dprint "find the node and pop it from the list.\n";
+ my $itr;
+ for ( $itr = $_[0]->begin; defined $itr; $itr = $itr->next ) {
+ last if ( $itr->next eq $_[-1] );
+ }
+ if ( not defined $itr ) {
+ warn "could not find the $_[-1] in the list: return undef";
+ return undef;
+ }
+ my $bye = delete $itr->[1];
+ $itr->[1] = delete $bye->[1];
+ return $bye;
+ }
+ elsif ( $_[-1] =~ /^(\+|-)?[0-9]+$/ ) {
+ ::dprint "pop the node at index of $_[-1] from the list.\n";
+ my $before;
+ my $count = $_[0]->count;
+ my $round = 0;
+
+ if ( $_[-1] < 0 ) {
+
+=pod
+
+If $N is greater than the size of the linked list
+then remove the first node of the list.
+
+ NOTE: Please use pure linked list implementation.
+ Example
+ Given Linked List: 1 -> 2 -> 3 -> 4 -> 5
+ when $N = 1
+ Output: 1 -> 2 -> 3 -> 4
+ when $N = 2
+ Output: 1 -> 2 -> 3 -> 5
+ when $N = 3
+ Output: 1 -> 2 -> 4 -> 5
+ when $N = 4
+ Output: 1 -> 3 -> 4 -> 5
+ when $N = 5
+ Output: 2 -> 3 -> 4 -> 5
+ when $N = 6
+ Output: 2 -> 3 -> 4 -> 5
+
+=cut
+
+ my $idx = $_[-1];
+ ::dprint ">> this is a task2 solution\n";
+
+ if ( -$idx > $count ) {
+ ::dprint ">>> always remove first node when index is".
+ " more than length of list.\n";
+
+ $before = $_[0]->[0];
+ ::dprint ">>>> and I have shortcut:".$before->value.$/;
+ }
+ else {
+ ::dprint ">>> we have to find index before the node".
+ " which will be removed.\n";
+ $round = -$idx;
+ ::dprint ">>>> index would be: $round\n";
+ }
+ }
+ if ( not defined $before ) {
+ $before = $_[0]->before_begin_;
+ ( $before = $before->next ) while $round--;
+ }
+ my $bye = delete $before->[1];
+ $before->[1] = delete $bye->[1];
+ return $bye;
+ }
+ else {
+ warn "invalid arguemnt for poping: ".($_[-1]//'<not given>');
+ return undef;
+ }
+ die "this is a bug" if $::debugging;
+}
+
+package linked_list::iterator;
+use Scalar::Util qw(blessed refaddr weaken isweak);
+
+sub new {
+ my $class = shift;
+ my $value = shift;
+ my $obj = [ $value, undef ];
+
+ weaken( $obj->[0] ) if refaddr( $obj->[0] );
+ bless $obj, ( blessed $class || $class );
+}
+
+sub next () { $_[0]->[1]; }
+sub value () { $_[0]->[0]; }
+
+sub DESTROY {
+ ::dprint "$_[0]: value: ".($_[0]->[0]||'<empty>')." destroyed!!!\n";
+}
+
+
+package main;
+
+sub get_actual_index_to_remove_ ( $$ ) { # have no type checking
+ my $list = shift;
+ my $N = shift;
+ my $count = $list->count;
+
+ return $count - $N; # -1 because index starts from 0
+}
+
+sub say_elements_ ( $;$ ) {
+ my $lst = shift;
+ my $index = shift;
+
+ my $itr = $lst->begin;
+ my $sep = ' -> ';
+ return if not defined $itr;
+
+ print $itr->value;
+ --$index if defined $index;
+ for ( my $i = 0, $itr = $itr->next; defined $itr; ++$i, $itr = $itr->next ) {
+ print $sep;
+ if ( defined $index and $index eq $i ) {
+ print( ( $::colour
+ ? colored( [ 'yellow on_black' ], $itr->value )
+ : '`'.$itr->value.'\'' ) );
+ }
+ else {
+ print $itr->value;
+ }
+ }
+ print $/;
+}
+
+my $example = linked_list->new( elements => [ 1..5 ] );
+print "Given Linked List: ";
+say_elements_( $example );
+
+for ( 1..6 ) {
+ my $idx = get_actual_index_to_remove_ $example, $_;
+ print "when \$N = $_\n";
+ if ( $::debugging ) {
+ ::dprint "Current: ";
+ say_elements_ $example, $idx;
+ }
+ my $clean_itr = $example->pop( -$idx ); # minus: from the end
+ print "Output: ";
+ say_elements_ $example;
+
+ # another hidden problem if we go through the loop
+ ::dprint "Inserting again for next try\n";
+ my $itr = $example->before_begin_;
+ for ( 0 .. $idx -1 ) { $itr = $itr->next; }
+ if ( defined $itr ) {
+ $example->push_back( $itr, $clean_itr );
+ }
+ else {
+ $example->push_back( $clean_itr );
+ }
+}
diff --git a/challenge-071/jeongoon/raku/ch-1.raku b/challenge-071/jeongoon/raku/ch-1.raku
new file mode 100644
index 0000000000..54274d2625
--- /dev/null
+++ b/challenge-071/jeongoon/raku/ch-1.raku
@@ -0,0 +1,67 @@
+#!/usr/bin/env raku
+# -*- Mode: Raku; indent-tabs-mode: nil; coding: utf-8 -*-
+# vim: set et ts=4 sw=4:
+
+class RandomList {
+ has @.list-all is rw = 1..42;
+ has Int $.num-of-list is rw = 9;
+
+ submethod BUILD ( :out-of(:@!list-all),
+ Int :selects(:$!num-of-list) ) {
+ }
+
+ method get-random-list () {
+ my $size = @!list-all.elems;
+
+ for ^$size {
+ my ( $lf, $ri ) = ( 0 ..^ $size ).rand.Int xx 2;
+ @!list-all[$lf, $ri] = @!list-all[$ri, $lf];
+ }
+ return @!list-all[0..^ $!num-of-list];
+ }
+}
+
+class PeakNum {
+ has ( $.left, $.mine ,$.right );
+ method lowest () { 0 }
+ method take () {
+ # XXX list-all itself contains Any type but check numerical only here.
+ take $!mine if $!mine > ( ($!left || self.lowest),
+ ($!right || self.lowest) ).all;
+ }
+}
+
+# $N == 1 isn't very harmful
+sub MAIN ( $N where { $N >= 1 } = 8, #= size of random numbers
+ Bool :$relax, #= loose strict rule in the challenge
+ :$max-number? where { $max-number >= $N } = 50,
+ ) {
+
+ #
+ if $relax.not {
+ die "\$N must be greater than 1" unless $N > 1;
+ if $max-number != 50 {
+ warn "max number is redeclared as 50";
+ $max-number = 50;
+ }
+ }
+
+ my $random-numbers = RandomList.new: :selects($N) :out-of(1 .. 50);
+ my $list = $random-numbers.get-random-list;
+ say "Array: " ~ $list.Array.raku;
+
+ my @peak-array = Array.new;
+ #if $N == 1 {
+ # @peak-array.
+ # append( PeakNum.new( :mine($list[0]) ) );
+ #}
+ #else {
+ for ^$N {
+ @peak-array.
+ append( PeakNum.new( :left( try $list[$_-1] )
+ :mine( $list[$_] ),
+ :right( try $list[$_+1] ) ) );
+ }
+ #}
+ say "Peak: " ~ gather { .take for @peak-array }.Array.raku;
+}
diff --git a/challenge-071/jeongoon/raku/ch-2.raku b/challenge-071/jeongoon/raku/ch-2.raku
new file mode 100644
index 0000000000..24a1c04e1b
--- /dev/null
+++ b/challenge-071/jeongoon/raku/ch-2.raku
@@ -0,0 +1,115 @@
+#!/usr/bin/env raku
+# -*- Mode: Raku; indent-tabs-mode: nil; coding: utf-8 -*-
+# vim: set et ts=4 sw=4:
+
+our $D = False;
+class LinkedList { ... }
+class Iter {
+ trusts LinkedList;
+ has $.value is rw;
+ has Iter $.next;
+
+ method is-last () { $!next.defined.not }
+
+ method !set-next ( Iter $another ) { $!next = $another }
+ method !reset-next () { $!next = Nil }
+ method !replace-next ( Iter:D $another ) {
+ my $prev-one = $!next;
+ $!next = $another;
+ return $prev-one;
+ }
+}
+
+class LinkedList {
+ has Iter $!core;
+ has Str $.sep = 'β†’';
+
+ method begin () returns Iter { $!core.next }
+
+ submethod BUILD {
+ $!core = Iter.new( :value( 'DO NOT REMOVE' ) );
+ }
+
+ method count () {
+ my $count = 0;
+ loop ( my $itr = self.begin; defined $itr; $itr = $itr.next ) {
+ ++$count
+ }
+ return $count;
+ }
+
+ # push back after an iterator and
+ # return another iterator which has moved forward
+ multi method push ( Any:D $that, Iter:D :$after ) {
+ my $itr = $that.isa( Iter ) ?? $that !! Iter.new( :value($that) );
+ say "push the node has (value: {$itr.value}) after node (value: {$after.value})" if $D;
+
+ $itr!Iter::set-next( $after!Iter::replace-next( $itr ) );
+ return $itr;
+ }
+
+ # push in the end of the list
+ multi method push ( Any:D $that ) returns Iter {
+ say "push in the end" if $D;
+ my $itr = $!core;
+ while $itr.next.defined { $itr = $itr.next }
+
+ my $node = $that.isa( Iter ) ?? $that !! Iter.new( :value( $that ) );
+ print " -> " if $D;
+ return self.push( $node, :after($itr) );
+ }
+
+ multi method push( # or unshift
+ Any:D $that, Int:D :$at is copy where * < self.count ) returns Iter {
+ # `-> Int:D needed not to be confused with
+ # 'multi method push ( Any:D $that )'
+ my $itr = $!core;
+ while ( $at-- ) { $itr = $itr.next }
+ return self.push( $that, :after($itr) );
+ }
+
+ multi method pop ( Iter:D :$after ) returns Iter {
+ my $go = $after.next;
+ if $go.defined {
+ $after!Iter::set-next( $go.next );
+ $go!Iter::reset-next();
+ }
+ return $go;
+ }
+ multi method pop ( Int:D :$at where * < self.count ) returns Iter {
+ my $itr = $!core;
+ for ^$at { $itr = $itr.next }
+ say "pop after node (value: {$itr.value})" if $D;
+ return self.pop( :after($itr) );
+ }
+
+ method say-values ( Str :$prompt? ) {
+ if $prompt.defined {
+ print( $prompt );
+ }
+ my $itr = self.begin;
+ $itr.value.print if $itr.defined;
+ loop ( $itr = $itr.next ; $itr.defined ; $itr = $itr.next ) {
+ print( " $!sep " ~ $itr.value );
+ }
+ say "";
+ }
+
+};
+
+sub MAIN ( Bool :debug($d) ) {
+ $D = $d;
+ my $List = LinkedList.new;
+
+ for 1 .. 5 -> $num { $List.push( $num ) }
+ for 1 .. 6 -> $N {
+ $List.say-values( :prompt( "Given List : " ) );
+
+ my $I = $List.count - $N;
+ $I = 0 if $I < 0; # given constraints
+
+ my $itr = $List.pop( :at($I) );
+ $List.say-values( :prompt("When \$N = $N\nOutput: " ) );
+ $List.push( $itr, :at($I) );
+ }
+}