From 99b1c57b60a71bff19a375944ffc3ea25a33bec2 Mon Sep 17 00:00:00 2001 From: Packy Anderson Date: Sun, 24 Sep 2023 22:42:24 -0400 Subject: Add blog.txt for challenge 235 --- challenge-235/packy-anderson/blog.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 challenge-235/packy-anderson/blog.txt diff --git a/challenge-235/packy-anderson/blog.txt b/challenge-235/packy-anderson/blog.txt new file mode 100644 index 0000000000..c00e34b301 --- /dev/null +++ b/challenge-235/packy-anderson/blog.txt @@ -0,0 +1 @@ +https://packy.dardan.com/2023/09/18/perl-weekly-challenge-remove-and-duplicate-challenge-edition/ \ No newline at end of file -- cgit From a758bddc3192ad92e3a6c6e8b35240921f33dabb Mon Sep 17 00:00:00 2001 From: Packy Anderson Date: Mon, 25 Sep 2023 18:32:52 -0400 Subject: Challenge 236 solutions by Packy Anderson Solutions in: * Perl * Raku * Python * Java One blog post. --- challenge-236/packy-anderson/blog.txt | 1 + challenge-236/packy-anderson/java/Ch1.java | 75 +++++++++++++++++++ challenge-236/packy-anderson/java/Ch2.java | 108 ++++++++++++++++++++++++++++ challenge-236/packy-anderson/perl/ch-1.pl | 61 ++++++++++++++++ challenge-236/packy-anderson/perl/ch-2.pl | 86 ++++++++++++++++++++++ challenge-236/packy-anderson/python/ch-1.py | 48 +++++++++++++ challenge-236/packy-anderson/python/ch-2.py | 73 +++++++++++++++++++ challenge-236/packy-anderson/raku/ch-1.raku | 56 +++++++++++++++ challenge-236/packy-anderson/raku/ch-2.raku | 81 +++++++++++++++++++++ 9 files changed, 589 insertions(+) create mode 100644 challenge-236/packy-anderson/blog.txt create mode 100644 challenge-236/packy-anderson/java/Ch1.java create mode 100644 challenge-236/packy-anderson/java/Ch2.java create mode 100755 challenge-236/packy-anderson/perl/ch-1.pl create mode 100755 challenge-236/packy-anderson/perl/ch-2.pl create mode 100755 challenge-236/packy-anderson/python/ch-1.py create mode 100755 challenge-236/packy-anderson/python/ch-2.py create mode 100755 challenge-236/packy-anderson/raku/ch-1.raku create mode 100755 challenge-236/packy-anderson/raku/ch-2.raku diff --git a/challenge-236/packy-anderson/blog.txt b/challenge-236/packy-anderson/blog.txt new file mode 100644 index 0000000000..0cb03145ca --- /dev/null +++ b/challenge-236/packy-anderson/blog.txt @@ -0,0 +1 @@ +https://packy.dardan.com/b/Bt \ No newline at end of file diff --git a/challenge-236/packy-anderson/java/Ch1.java b/challenge-236/packy-anderson/java/Ch1.java new file mode 100644 index 0000000000..8e7734182b --- /dev/null +++ b/challenge-236/packy-anderson/java/Ch1.java @@ -0,0 +1,75 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.HashMap; +import java.util.List; + +public class Ch1 { + public static boolean isExactChangePossible(int[] bills) { + // we keep the bills in a "till" + HashMap till = + new HashMap(); + + for (int collected : bills) { + // put the bill we collected in the "till" + // + // using .getOrDefault(collected, 0) yields the value + // in the map for the key 'collected' if it exists, or + // the specified default (in this case, 0) if it doesn't + till.put( + collected, + till.getOrDefault(collected, 0) + 1 + ); + + // calculate the required change + int change_required = collected - 5; + + // loop through the bills we have on hand, making sure + // we go from largest to smallest bill + List keys = new ArrayList<>(till.keySet()); + Collections.sort(keys, Collections.reverseOrder()); + for (Integer bill : keys) { + // as long as we have more of this bill and + // using it would not yield TOO MUCH change + while (till.get(bill) > 0 && + change_required - bill >= 0) { + // deduct the amount from the required change + change_required -= bill; + + // remove the bill from the till + till.put(bill, till.get(bill) - 1); + } + } + // if we weren't able to make change, fail + if (change_required > 0) { + return false; + } + } + return true; + } + + public static String joined(int[] ints) { + // we're using it more than once, make it a method + return Arrays.stream(ints) + .mapToObj(String::valueOf) + .collect(Collectors.joining(", ")); + } + + public static void solution(int[] bills) { + System.out.println("Input: @bills = (" + joined(bills) + ")"); + boolean output = isExactChangePossible(bills); + System.out.println("Output: " + output); + } + + public static void main(String[] args) { + System.out.println("Example 1:"); + solution(new int[] {5, 5, 5, 10, 20}); + + System.out.println("\nExample 2:"); + solution(new int[] {5, 5, 10, 10, 20}); + + System.out.println("\nExample 3:"); + solution(new int[] {5, 5, 5, 20}); + } +} \ No newline at end of file diff --git a/challenge-236/packy-anderson/java/Ch2.java b/challenge-236/packy-anderson/java/Ch2.java new file mode 100644 index 0000000000..f19044cf90 --- /dev/null +++ b/challenge-236/packy-anderson/java/Ch2.java @@ -0,0 +1,108 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.stream.Collectors; + +public class Ch2 { + public static ArrayList loopExistsAt( + int start, int[] ints, HashMap seen + ) { + // bail early if we're in a loop we've seen before + if (seen.get(start) != null) { + // return an empty ArrayList + return new ArrayList(); + } + + // initialize an empty list to start + ArrayList loop = new ArrayList(); + // initialize i to starting point + int i = start; + while (true) { + // keep track of the values in the order we visit them + loop.add(ints[i]); + + // track where we've already been + // to avoid double-counting loops + seen.put(i, 1); + + // get the next index + i = ints[i]; + + // make sure the index is in bounds + if (i < 0 || i >= ints.length) { + break; + } + + // make sure we haven't seen the index before + if (seen.get(i) != null) { + break; + } + } + + // if the last element points back to + // the start, it's a loop! + if (loop.get(loop.size() - 1) == start) { + return loop; + } + + // otherwise, return an empty ArrayList + return new ArrayList(); + } + + public static ArrayList> identifyLoops(int[] ints) { + ArrayList> loops = + new ArrayList>(); + HashMap seen = + new HashMap(); + + for (int i = 0; i < ints.length; i++) { + ArrayList loop = loopExistsAt(i, ints, seen); + if (loop.size() > 0) { + loops.add(loop); + } + } + return loops; + } + + public static String comma_joined(int[] ints) { + // we're using it more than once, make it a method + return Arrays.stream(ints) + .mapToObj(String::valueOf) + .collect(Collectors.joining(",")); + } + + public static void solution(int[] ints) { + System.out.println("Input: @ints = (" + comma_joined(ints) + + ")"); + ArrayList> loops = identifyLoops(ints); + int count = loops.size(); + System.out.println(String.format("Output: %1$d", count)); + if (count > 0) { + String loop_noun = (count == 1) ? "Loop" : "Loops"; + String are_verb = (count == 1) ? "is" : "are"; + System.out.println("\n" + loop_noun + " " + are_verb + + " as below:"); + + for (ArrayList loop : loops) { + String as_list = loop.stream() + .map(String::valueOf) + .collect(Collectors.joining(" ")); + System.out.println("[" + as_list + "]"); + } + } + } + + public static void main(String[] args) { + System.out.println("Example 1:"); + solution(new int[] {4,6,3,8,15,0,13,18,7,16,14, + 19,17,5,11,1,12,2,9,10}); + + System.out.println("\nExample 2:"); + solution(new int[] {0,1,13,7,6,8,10,11,2,14,16, + 4,12,9,17,5,3,18,15,19}); + + System.out.println("\nExample 3:"); + solution(new int[] {9,8,3,11,5,7,13,19,12,4,14, + 10,18,2,16,1,0,15,6,17}); + } +} diff --git a/challenge-236/packy-anderson/perl/ch-1.pl b/challenge-236/packy-anderson/perl/ch-1.pl new file mode 100755 index 0000000000..ae365bfbd8 --- /dev/null +++ b/challenge-236/packy-anderson/perl/ch-1.pl @@ -0,0 +1,61 @@ +#!/usr/bin/env perl + +use v5.38; +use Data::Dumper::Concise; + +sub isExactChangePossible { + my @bills = @_; + my %till; # we keep the bills in a "till" + BILLS: foreach my $collected ( @bills ) { + # put the bill we collected in the "till" + $till{$collected}++; + + # calculate the required change + my $change_required = $collected - 5; + + # if we don't need to make change, + # skip to the next bill collected! + next BILLS unless $change_required; + + # loop through the bills we have on hand + # in descending size (try to make change + # with the largest bills possible) + foreach my $bill ( reverse sort { $a <=> $b } keys %till ) { + + # as long as we have more of this bill and + # using it would not yield TOO MUCH change + while ( $till{$bill} > 0 && $change_required - $bill >= 0 ) { + # deduct the amount from the required change + $change_required -= $bill; + + # remove the bill from the till + $till{$bill}--; + } + + # move on if we managed to make exact change! + next BILLS unless $change_required; + } + + # if we weren't able to make change, fail + return 0 if $change_required; + } + + # we successfully made change for all transactions! + return 1; +} + +sub solution { + my @bills = @_; + say 'Input: @bills = (' . join(', ', @bills) . ')'; + my $output = isExactChangePossible(@bills); + say 'Output: ' . ($output ? 'true' : 'false'); +} + +say "Example 1:"; +solution(5, 5, 5, 10, 20); + +say "\nExample 2:"; +solution(5, 5, 10, 10, 20); + +say "\nExample 3:"; +solution(5, 5, 5, 20); \ No newline at end of file diff --git a/challenge-236/packy-anderson/perl/ch-2.pl b/challenge-236/packy-anderson/perl/ch-2.pl new file mode 100755 index 0000000000..4ae4072f83 --- /dev/null +++ b/challenge-236/packy-anderson/perl/ch-2.pl @@ -0,0 +1,86 @@ +#!/usr/bin/env perl + +use v5.38; + +use Lingua::EN::Inflexion qw( inflect ); + +sub loopExistsAt { + my %params = @_; + my $ints = $params{ints}; + my $start = $params{start}; + my $seen = $params{seen}; + + # bail early if we're in a loop we've seen before + return if exists $seen->{$start}; + + my @loop; + my $i = $start; + for (;;) { + # keep track of the values in the order we visit them + push @loop, $ints->[$i]; + + # track where we've already been + # to avoid double-counting loops + $seen->{$i} = 1; + + # get the next index + $i = $ints->[$i]; + + # make sure the index is in bounds + last unless $i >= 0 && $i <= $#{$ints}; + + # make sure we haven't seen the index before + last if exists $seen->{$i}; + } + + # if the last element points back to + # the start, it's a loop! + if ($loop[-1] == $start) { + return @loop; + } + # otherwise, return an empty list + return; +} + +sub identifyLoops { + my @ints = @_; + my @loops; + my %seen; # keep track of indices we've seen + # to avoid duplicating loops + foreach my $start ( 0 .. $#ints ) { + my @loop = loopExistsAt( + start => $start, + ints => \@ints, + seen => \%seen + ); + if (@loop) { + push @loops, \@loop; + } + } + return @loops; +} + +sub solution { + my @ints = @_; + say 'Input: @ints = (' . join(',', @ints) . ')'; + my @loops = identifyLoops(@ints); + say 'Output: ' . scalar(@loops); + + if (@loops) { + my $count = scalar(@loops); + + say inflect "\n<#d:$count> as below:"; + foreach my $loop ( @loops ) { + say '[' . join(' ', @$loop) . ']'; + } + } +} + +say "Example 1:"; +solution(4,6,3,8,15,0,13,18,7,16,14,19,17,5,11,1,12,2,9,10); + +say "\nExample 2:"; +solution(0,1,13,7,6,8,10,11,2,14,16,4,12,9,17,5,3,18,15,19); + +say "\nExample 3:"; +solution(9,8,3,11,5,7,13,19,12,4,14,10,18,2,16,1,0,15,6,17); \ No newline at end of file diff --git a/challenge-236/packy-anderson/python/ch-1.py b/challenge-236/packy-anderson/python/ch-1.py new file mode 100755 index 0000000000..75ccdda4b6 --- /dev/null +++ b/challenge-236/packy-anderson/python/ch-1.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +def isExactChangePossible(bills): + till = {}; # we keep the bills in a "till" + for collected in bills: + # put the bill we collected in the "till" + # + # using .get(collected, 0) yields the value in the + # dict for the key 'collected' if it exists, or the + # specified default (in this case, 0) if it doesn't + till[collected] = till.get(collected, 0) + 1 + + # calculate the required change + change_required = collected - 5 + + # loop through the bills we have on hand + for bill in sorted(till, reverse=True): + # as long as we have more of this bill and + # using it would not yield TOO MUCH change + while till[bill] > 0 and change_required - bill >= 0: + # deduct the amount from the required change + change_required -= bill + + # remove the bill from the till + till[bill] -= 1 + + # if we weren't able to make change, fail + if change_required: + return 0 + + # we successfully made change for all transactions! + return 1 + +def solution(bills): + as_list = ', '.join(map(lambda i: str(i), bills)) + print(f'Input: @bills = ({as_list})') + output = isExactChangePossible(bills) + print(f'Output: {"true" if output else "false"}') + + +print('Example 1:') +solution([5, 5, 5, 10, 20]) + +print('\nExample 2:') +solution([5, 5, 10, 10, 20]) + +print('\nExample 3:') +solution([5, 5, 5, 20]) \ No newline at end of file diff --git a/challenge-236/packy-anderson/python/ch-2.py b/challenge-236/packy-anderson/python/ch-2.py new file mode 100755 index 0000000000..81d1f04ab7 --- /dev/null +++ b/challenge-236/packy-anderson/python/ch-2.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python + +def loopExistsAt(ints=[], seen={}, start=0): + # bail early if we're in a loop we've seen before + if start in seen: + return [] + + loop = [] # initialize an empty list to start + i = start # initialize i to starting point + while True: + # keep track of the values in the order we visit them + loop.append(ints[i]) + + # track where we've already been + # to avoid double-counting loops + seen[i] = 1 + + # get the next index + i = ints[i] + + # make sure the index is in bounds + if i < 0 or i >= len(ints): + break + + # make sure we haven't seen the index before + if i in seen: + break + + # if the last element points back to + # the start, it's a loop! + if loop[-1] == start: + return loop + + # otherwise, return an empty list + return [] + +def identifyLoops(ints): + loops = [] + seen = {}; # keep track of indices we've seen + # to avoid duplicating loops + for start in range(0, len(ints)): + loop = loopExistsAt( + start = start, + ints = ints, + seen = seen + ) + if loop: + loops.append(loop) + return loops + +def solution(ints): + as_list = ','.join(map(lambda i: str(i), ints)) + print(f'Input: @ints = ({as_list})') + loops = identifyLoops(ints) + count = len(loops) + print(f'Output: {count}') + if count: + loop_noun = "Loops" if count != 1 else "Loop" + are_verb = "are" if count != 1 else "is" + print(f'\n{loop_noun} {are_verb} as below:') + for loop in loops: + as_list = ' '.join(map(lambda i: str(i), loop)) + print(f'[{as_list}]') + + +print('Example 1:') +solution([4,6,3,8,15,0,13,18,7,16,14,19,17,5,11,1,12,2,9,10]) + +print('\nExample 2:') +solution([0,1,13,7,6,8,10,11,2,14,16,4,12,9,17,5,3,18,15,19]) + +print('\nExample 3:') +solution([9,8,3,11,5,7,13,19,12,4,14,10,18,2,16,1,0,15,6,17]) \ No newline at end of file diff --git a/challenge-236/packy-anderson/raku/ch-1.raku b/challenge-236/packy-anderson/raku/ch-1.raku new file mode 100755 index 0000000000..0e5dd99983 --- /dev/null +++ b/challenge-236/packy-anderson/raku/ch-1.raku @@ -0,0 +1,56 @@ +#!/usr/bin/env raku + +use v6; + +sub isExactChangePossible(*@bills where ($_.all ~~ Int)) { + my %till; # we keep the bills in a "till" + BILLS: for @bills -> $collected { + # put the bill we collected in the "till" + %till{$collected}++; + + # calculate the required change + my $change_required = $collected - 5; + + # if we don't need to make change, + # skip to the next bill collected! + next BILLS unless $change_required; + + # loop through the bills we have on hand + for %till.keys().sort({ .Int }).reverse() -> $bill { + # as long as we have more of this bill and + # using it would not yield TOO MUCH change + while ( %till{$bill} > 0 && $change_required - $bill >= 0 ) { + # deduct the amount from the required change + $change_required -= $bill; + + # remove the bill from the till + %till{$bill}--; + } + + # move on if we managed to make exact change! + next BILLS unless $change_required; + } + + # if we weren't able to make change, fail + return 0 if $change_required; + } + + # we successfully made change for all transactions! + return 1; +} + +sub solution { + my @bills = @_; + say 'Input: @bills = (' ~ @bills.join(', ') ~ ')'; + my $output = isExactChangePossible(@bills); + say 'Output: ' ~ ($output ?? 'true' !! 'false'); +} + +say "Example 1:"; +solution(5, 5, 5, 10, 20); + +say "\nExample 2:"; +solution(5, 5, 10, 10, 20); + +say "\nExample 3:"; +solution(5, 5, 5, 20); \ No newline at end of file diff --git a/challenge-236/packy-anderson/raku/ch-2.raku b/challenge-236/packy-anderson/raku/ch-2.raku new file mode 100755 index 0000000000..0660e70210 --- /dev/null +++ b/challenge-236/packy-anderson/raku/ch-2.raku @@ -0,0 +1,81 @@ +#!/usr/bin/env raku + +use v6; + +sub loopExistsAt(:@ints, :$start, :%seen) { + # bail early if we're in a loop we've seen before + return [] if %seen{$start}:exists; + + my @loop; + my $i = $start; + loop (;;) { + # keep track of the values in the order we visit them + push @loop, @ints[$i]; + + # track where we've already been + # to avoid double-counting loops + %seen{$i} = 1; + + # get the next index + $i = @ints[$i]; + + # make sure the index is in bounds + last unless $i >= 0 && $i < @ints.elems; + + # make sure we haven't seen the index before + last if %seen{$i}:exists; + } + + # if the last element points back to + # the start, it's a loop! + if (@loop[*-1] == $start) { + return @loop; + } + # otherwise, return an empty list + return []; +} + +sub identifyLoops { + my @ints = @_; + my @loops; + my %seen; # keep track of indices we've seen + # to avoid duplicating loops + for 0 .. $@ints.elems - 1 -> $start { + my @loop = loopExistsAt( + start => $start, + ints => @ints, + seen => %seen + ); + if (@loop) { + push @loops, @loop; + } + } + return @loops; +} + +sub solution { + my @ints = @_; + say 'Input: @ints = (' ~ @ints.join(',') ~ ')'; + my @loops = identifyLoops(@ints); + my $count = @loops.elems; + say "Output: $count"; + + if (@loops) { + my $loops = $count != 1 ?? 'Loops' !! 'Loop'; + my $are = $count != 1 ?? 'are' !! 'is'; + + say "\n$loops $are as below:"; + for @loops -> @loop { + say '[' ~ @loop.join(' ') ~ ']'; + } + } +} + +say "Example 1:"; +solution(4,6,3,8,15,0,13,18,7,16,14,19,17,5,11,1,12,2,9,10); + +say "\nExample 2:"; +solution(0,1,13,7,6,8,10,11,2,14,16,4,12,9,17,5,3,18,15,19); + +say "\nExample 3:"; +solution(9,8,3,11,5,7,13,19,12,4,14,10,18,2,16,1,0,15,6,17); \ No newline at end of file -- cgit From a1181eddd928dc666a9a408d648e25d12426e6b8 Mon Sep 17 00:00:00 2001 From: Packy Anderson Date: Mon, 25 Sep 2023 18:40:35 -0400 Subject: Fix blog URL and add changed to README --- challenge-236/packy-anderson/README.md | 78 ++++++++++++++++++++++------------ challenge-236/packy-anderson/blog.txt | 2 +- 2 files changed, 52 insertions(+), 28 deletions(-) diff --git a/challenge-236/packy-anderson/README.md b/challenge-236/packy-anderson/README.md index f957013c00..54468a7f26 100644 --- a/challenge-236/packy-anderson/README.md +++ b/challenge-236/packy-anderson/README.md @@ -8,20 +8,16 @@ Sample output ``` $ perl/ch-1.pl Example 1: -Input: @ints = (0, 2, 9, 4, 6) +Input: @bills = (5, 5, 5, 10, 20) Output: true Example 2: -Input: @ints = (5, 1, 3, 2) +Input: @bills = (5, 5, 10, 10, 20) Output: false Example 3: -Input: @ints = (2, 2, 3) +Input: @bills = (5, 5, 5, 20) Output: true - -Example 4 from James Curtis-Smith: -Input: @ints = (1, 2, 3, 4, 1, 2, 3) -Output: false ``` * [Task 2](perl/ch-2.pl) @@ -30,16 +26,32 @@ Sample output ``` $ perl/ch-2.pl Example 1: -Input: @ints = (1, 0, 2, 3, 0, 4, 5, 0) -Output: (1, 0, 0, 2, 3, 0, 0, 4) +Input: @ints = (4,6,3,8,15,0,13,18,7,16,14,19,17,5,11,1,12,2,9,10) +Output: 3 + +Loops are as below: +[4 15 1 6 13 5 0] +[3 8 7 18 9 16 12 17 2] +[14 11 19 10] Example 2: -Input: @ints = (1, 2, 3) -Output: (1, 2, 3) +Input: @ints = (0,1,13,7,6,8,10,11,2,14,16,4,12,9,17,5,3,18,15,19) +Output: 6 + +Loops are as below: +[0] +[1] +[13 9 14 17 18 15 5 8 2] +[7 11 4 6 10 16 3] +[12] +[19] Example 3: -Input: @ints = (0, 3, 0, 4, 5) -Output: (0, 0, 3, 0, 0) +Input: @ints = (9,8,3,11,5,7,13,19,12,4,14,10,18,2,16,1,0,15,6,17) +Output: 1 + +Loop is as below: +[9 4 5 7 19 17 15 1 8 12 18 6 13 2 3 11 10 14 16 0] ``` ## Raku @@ -50,20 +62,16 @@ Sample output ``` $ raku/ch-1.raku Example 1: -Input: @ints = (0, 2, 9, 4, 6) +Input: @bills = (5, 5, 5, 10, 20) Output: true Example 2: -Input: @ints = (5, 1, 3, 2) +Input: @bills = (5, 5, 10, 10, 20) Output: false Example 3: -Input: @ints = (2, 2, 3) +Input: @bills = (5, 5, 5, 20) Output: true - -Example 4 from James Curtis-Smith: -Input: @ints = (1, 2, 3, 4, 1, 2, 3) -Output: false ``` * [Task 2](raku/ch-2.raku) @@ -72,16 +80,32 @@ Sample output ``` $ raku/ch-2.raku Example 1: -Input: @ints = (1, 0, 2, 3, 0, 4, 5, 0) -Output: (1, 0, 0, 2, 3, 0, 0, 4) +Input: @ints = (4,6,3,8,15,0,13,18,7,16,14,19,17,5,11,1,12,2,9,10) +Output: 3 + +Loops are as below: +[4 15 1 6 13 5 0] +[3 8 7 18 9 16 12 17 2] +[14 11 19 10] Example 2: -Input: @ints = (1, 2, 3) -Output: (1, 2, 3) +Input: @ints = (0,1,13,7,6,8,10,11,2,14,16,4,12,9,17,5,3,18,15,19) +Output: 6 + +Loops are as below: +[0] +[1] +[13 9 14 17 18 15 5 8 2] +[7 11 4 6 10 16 3] +[12] +[19] Example 3: -Input: @ints = (0, 3, 0, 4, 5) -Output: (0, 0, 3, 0, 0) +Input: @ints = (9,8,3,11,5,7,13,19,12,4,14,10,18,2,16,1,0,15,6,17) +Output: 1 + +Loop is as below: +[9 4 5 7 19 17 15 1 8 12 18 6 13 2 3 11 10 14 16 0] ``` ## Guest Language: Python @@ -94,4 +118,4 @@ Output: (0, 0, 3, 0, 0) ## Blog Post -[Perl Weekly Challenge: Remove and Duplicate, Challenge Edition](https://packy.dardan.com/2023/09/18/perl-weekly-challenge-remove-and-duplicate-challenge-edition/) +[Perl Weekly Challenge: Exact Change and Array Loops](https://packy.dardan.com/2023/09/25/perl-weekly-challenge-exact-change-and-array-loops/) diff --git a/challenge-236/packy-anderson/blog.txt b/challenge-236/packy-anderson/blog.txt index 0cb03145ca..c80696d566 100644 --- a/challenge-236/packy-anderson/blog.txt +++ b/challenge-236/packy-anderson/blog.txt @@ -1 +1 @@ -https://packy.dardan.com/b/Bt \ No newline at end of file +https://packy.dardan.com/2023/09/25/perl-weekly-challenge-exact-change-and-array-loops/ \ No newline at end of file -- cgit From 81695c46183ba0154c05412705e0e85a632d32a0 Mon Sep 17 00:00:00 2001 From: Simon Green Date: Mon, 2 Oct 2023 17:25:37 +1100 Subject: Simon's solution to challenge 236 --- challenge-236/sgreen/README.md | 4 +-- challenge-236/sgreen/blog.txt | 1 + challenge-236/sgreen/perl/ch-1.pl | 49 +++++++++++++++++++++++++++++++++++++ challenge-236/sgreen/perl/ch-2.pl | 42 +++++++++++++++++++++++++++++++ challenge-236/sgreen/python/ch-1.py | 42 +++++++++++++++++++++++++++++++ challenge-236/sgreen/python/ch-2.py | 38 ++++++++++++++++++++++++++++ 6 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 challenge-236/sgreen/blog.txt create mode 100755 challenge-236/sgreen/perl/ch-1.pl create mode 100755 challenge-236/sgreen/perl/ch-2.pl create mode 100755 challenge-236/sgreen/python/ch-1.py create mode 100755 challenge-236/sgreen/python/ch-2.py diff --git a/challenge-236/sgreen/README.md b/challenge-236/sgreen/README.md index f06edcdb27..c3256674bf 100644 --- a/challenge-236/sgreen/README.md +++ b/challenge-236/sgreen/README.md @@ -1,3 +1,3 @@ -# The Weekly Challenge 235 +# The Weekly Challenge 236 -Blog: [Adding and removing integers](https://dev.to/simongreennet/adding-and-removing-integers-3i4g) +Blog: [Juicy loops](https://dev.to/simongreennet/juicy-loops-2di2) diff --git a/challenge-236/sgreen/blog.txt b/challenge-236/sgreen/blog.txt new file mode 100644 index 0000000000..d76a60ea88 --- /dev/null +++ b/challenge-236/sgreen/blog.txt @@ -0,0 +1 @@ +https://dev.to/simongreennet/juicy-loops-2di2 \ No newline at end of file diff --git a/challenge-236/sgreen/perl/ch-1.pl b/challenge-236/sgreen/perl/ch-1.pl new file mode 100755 index 0000000000..246983d32d --- /dev/null +++ b/challenge-236/sgreen/perl/ch-1.pl @@ -0,0 +1,49 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use feature 'say'; +use experimental 'signatures'; + +use List::Util 'min'; + +sub main (@notes) { + # Store what is in the wallet, key is the dollar value, value is the + # number of notes we have + my %wallet = (); + + C: foreach my $customer_note (@notes) { + # Add the amount the person has given us + $wallet{$customer_note}++; + + if ( $customer_note == 5 ) { + # No change required :) + next; + } + + my $change = $customer_note - 5; + + # We try the bigger notes first + foreach my $wallet_note ( sort { $b <=> $a } keys %wallet ) { + my $note_count = + min( $wallet{$wallet_note}, int( $change / $wallet_note ) ); + if ( $note_count > 0 ) { + # Take the note from the wallet, and reduce the change still + # to give + $wallet{$wallet_note} -= $note_count; + $change -= $wallet_note * $note_count; + + if ( $change == 0 ) { + next C; + } + } + } + + say 'false'; + return; + } + + say 'true'; +} + +main(@ARGV); \ No newline at end of file diff --git a/challenge-236/sgreen/perl/ch-2.pl b/challenge-236/sgreen/perl/ch-2.pl new file mode 100755 index 0000000000..db13ccb43d --- /dev/null +++ b/challenge-236/sgreen/perl/ch-2.pl @@ -0,0 +1,42 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use feature 'say'; +use experimental 'signatures'; + +use List::Util 'any'; + +sub main (@ints) { + # Record all the loops we find + my $loops = 0; + + F: foreach my $first ( 0 .. $#ints ) { + my @loop = (); + my $pos = $first; + + while ( $pos >= 0 and $pos <= $#ints and defined( $ints[$pos] ) ) { + push @loop, $pos; + + # What is the next number + my $next_pos = $ints[$pos]; + + # Mark this position as used + $ints[$pos] = undef; + + if ( any { $next_pos == $_ } @loop ) { + # We have a loop + ++$loops; + next F; + } + + # Continue with the next position + $pos = $next_pos; + } + } + + # Print the loops we found + say $loops; +} + +main(@ARGV); \ No newline at end of file diff --git a/challenge-236/sgreen/python/ch-1.py b/challenge-236/sgreen/python/ch-1.py new file mode 100755 index 0000000000..80ff481963 --- /dev/null +++ b/challenge-236/sgreen/python/ch-1.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 + +import sys + + +def main(notes): + # Store what is in the wallet, key is the dollar value, value is the + # number of notes we have + wallet = {} + + for customer_note in notes: + # Add the amount the person has given us + wallet[customer_note] = wallet.get(customer_note, 0) + 1 + + if customer_note == 5: + # No change required :) + continue + + change = customer_note - 5 + + # We try the bigger notes first + for wallet_note in sorted(wallet, reverse=True): + note_count = min(wallet[wallet_note], change // wallet_note) + if note_count > 0: + # Take the note from the wallet, and reduce the change still + # to give + wallet[wallet_note] -= note_count + change -= wallet_note * note_count + + if change == 0: + break + else: + print('false') + return + + print('true') + + +if __name__ == '__main__': + # Convert input into integers + array = [int(n) for n in sys.argv[1:]] + main(array) diff --git a/challenge-236/sgreen/python/ch-2.py b/challenge-236/sgreen/python/ch-2.py new file mode 100755 index 0000000000..c0b0911a80 --- /dev/null +++ b/challenge-236/sgreen/python/ch-2.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 + +import sys + + +def main(ints): + # Record all the loops we find + loops = 0 + + for first in range(len(ints)): + loop = [] + pos = first + + while pos >= 0 and pos < len(ints) and ints[pos] is not None: + loop.append(pos) + + # What is the next number + next_pos = ints[pos] + + # Mark this position as used + ints[pos] = None + + if next_pos in loop: + # We have a loop + loops += 1 + break + + # Continue with the next position + pos = next_pos + + # Print the loops we found + print(loops) + + +if __name__ == '__main__': + # Convert input into integers + array = [int(n) for n in sys.argv[1:]] + main(array) -- cgit From bacdcb950c6fbf6dec2e2c23b8999681a897c226 Mon Sep 17 00:00:00 2001 From: rcmlz Date: Mon, 2 Oct 2023 15:50:25 +0200 Subject: solutions ch-237 --- challenge-237/rcmlz/raku/task-one.rakumod | 18 ++++++++++++++++++ challenge-237/rcmlz/raku/task-two.rakumod | 15 +++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 challenge-237/rcmlz/raku/task-one.rakumod create mode 100644 challenge-237/rcmlz/raku/task-two.rakumod diff --git a/challenge-237/rcmlz/raku/task-one.rakumod b/challenge-237/rcmlz/raku/task-one.rakumod new file mode 100644 index 0000000000..be3bf53f5c --- /dev/null +++ b/challenge-237/rcmlz/raku/task-one.rakumod @@ -0,0 +1,18 @@ +unit module rcmlz::raku::task-one:ver<0.0.1>:auth:api<1>; + +# run in terminal: raku --optimize=3 -I challenge-nr237/rcmlz/raku/ -- test/challenge-nr237/raku/task-one.rakutest +# or raku --optimize=3 -I challenge-nr237 -- test/benchmark-scalabiity.raku --task=task-one --user=rcmlz --max-run-times=1,3,7 --max-problem=10 --v=True --test-before-benchmark=True --out-folder=/tmp nr237; cat /tmp/nr237_task-one.csv + +#|[ +Given a year, a month, a weekday of month, and a day of week (1 (Mon) .. 7 (Sun)), +- print the day. +] +our sub solution(%input) is export { + my $last-day-in-month = Date.new(%input, %input, *).day; + my $counter = %input; + for 1..$last-day-in-month -> $dom { + $counter-- if %input == Date.new(%input, %input, $dom).day-of-week; + return $dom unless $counter + } + return 0 +} \ No newline at end of file diff --git a/challenge-237/rcmlz/raku/task-two.rakumod b/challenge-237/rcmlz/raku/task-two.rakumod new file mode 100644 index 0000000000..fad8abe467 --- /dev/null +++ b/challenge-237/rcmlz/raku/task-two.rakumod @@ -0,0 +1,15 @@ +unit module rcmlz::raku::task-two:ver<0.0.1>:auth:api<1>; + +# run in terminal: raku --optimize=3 -I challenge-nr237/rcmlz/raku/ -- test/challenge-nr237/raku/task-two.rakutest +# or raku --optimize=3 -I challenge-nr237 -- test/benchmark-scalabiity.raku --task=task-two --user=rcmlz --max-run-times=1,3,7 --max-problem=10 --v=True --test-before-benchmark=True --out-folder=/tmp nr237; cat /tmp/nr237_task-two.csv + +#|[ +You are given an array of integers. + +- Write a script to permute the given array such that you get the maximum possible greatness. +- To determine greatness: nums[i] < perm[i] where 0 <= i < nums.length +] +our sub solution(@input) is export { + my @sorted = @input.sort; + [+] (@sorted.reverse Z- @sorted).grep(* > 0) +} \ No newline at end of file -- cgit From e3e576cf34c7feef5e679398f3069922766c5df1 Mon Sep 17 00:00:00 2001 From: David Ferrone Date: Mon, 2 Oct 2023 10:32:35 -0400 Subject: Week 237 --- challenge-237/zapwai/perl/ch-1.pl | 61 +++++++++++++++++++++++++++++++++++++++ challenge-237/zapwai/perl/ch-2.pl | 35 ++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 challenge-237/zapwai/perl/ch-1.pl create mode 100644 challenge-237/zapwai/perl/ch-2.pl diff --git a/challenge-237/zapwai/perl/ch-1.pl b/challenge-237/zapwai/perl/ch-1.pl new file mode 100644 index 0000000000..f1d3d8ee3d --- /dev/null +++ b/challenge-237/zapwai/perl/ch-1.pl @@ -0,0 +1,61 @@ +use v5.30; +# Given yr, month, week, day (1 (Mon) .. 7 (Sun)), print date +my ($year, $month, $week, $day) = (2024, 4, 3, 2); +#my ($year, $month, $week, $day) = (2025, 10, 2, 4); +#my ($year, $month, $week, $day) = (2026, 8, 5, 3); + +my @d = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); +$d[1]++ if (is_leap($year)); + +sub is_leap { + my $year = shift; + my $ans = 0; + unless ( $year % 100 == 0 ) { + $ans = 1 if ( $year % 4 == 0 ); + } + $ans = 1 if ( $year % 400 == 0 ); + return $ans; +} + +sub start_day { + my $year = shift; + my @day = ('1', '2', '3', '4', '5', '6', '7'); + my $steps = ($year - 1753) % 400; + my $cnt = 0; + unless ($steps == 0) { + for my $i (1 .. $steps) { + $cnt = ($cnt + 1) % 7; + $cnt = ($cnt + 1) % 7 + if (is_leap(-1 + $year + $i - $steps)); + } + } + return $day[$cnt]; +} + +sub month_start_day { + my ($year, $month) = @_; + my $start = start_day($year) - 1; # 0 to 6 + my $cnt = $month - 1; + my $n = 0; + while ($cnt > 0) { + $cnt--; + $start += $d[$n]; + $start %= 7; + $n++; + } + return (1 + $start); +} + +my $date = 1; +my $start_day = month_start_day($year, $month); +my $diff = $day - $start_day; +my $n = $week - 1; +$date += $diff; +$date += $n * 7; +$date += 7 if ($diff < 0); +$date = 0 if ($date > $d[$month-1]); +say "Input: (\$year, \$month, \$week, \$day) = ($year, $month, $week, $day)"; +say "Output: $date"; +if ($date == 0) { + say "\t(No such date.)"; +} diff --git a/challenge-237/zapwai/perl/ch-2.pl b/challenge-237/zapwai/perl/ch-2.pl new file mode 100644 index 0000000000..9f71d22ad5 --- /dev/null +++ b/challenge-237/zapwai/perl/ch-2.pl @@ -0,0 +1,35 @@ +use v5.30; +my @nums = (1, 3, 5, 2, 1, 3, 1); +say "Input: \@nums = (" . join(", ",@nums) . ")"; +my %loc; +for my $i (0 .. $#nums) { + if ($loc{$nums[$i]}) { + my @list = @{$loc{$nums[$i]}}; + push @list, $i; + $loc{$nums[$i]} = \@list; + } else { + $loc{$nums[$i]} = [$i]; + } +} +my @perm; +my @tube = sort { $a <=> $b } @nums; +my @value = reverse sort { $a <=> $b } keys %loc; +foreach my $i (@{$loc{$value[0]}}) { + $perm[$i] = shift @tube; +} +shift @value; +for my $j (@value) { + foreach my $i (@{$loc{$j}}) { + if ($nums[$i] < $tube[$#tube]) { + $perm[$i] = pop @tube; + } + else { + $perm[$i] = shift @tube; + } + } +} +my $cnt; +foreach my $i (0 .. $#nums) { + $cnt++ if ($nums[$i] < $perm[$i]); +} +say "Output: $cnt \n\t\t(".join(", ",@perm).")"; -- cgit From 46450c7c251ec5f0e00aa512ef6ae3dfcfc247c3 Mon Sep 17 00:00:00 2001 From: Luis Mochan Date: Mon, 2 Oct 2023 11:09:31 -0600 Subject: Solve PWC237 --- challenge-237/wlmb/blog.txt | 1 + challenge-237/wlmb/perl/ch-1.pl | 38 ++++++++++++++++++++++++++++++++++++++ challenge-237/wlmb/perl/ch-2.pl | 18 ++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 challenge-237/wlmb/blog.txt create mode 100755 challenge-237/wlmb/perl/ch-1.pl create mode 100755 challenge-237/wlmb/perl/ch-2.pl diff --git a/challenge-237/wlmb/blog.txt b/challenge-237/wlmb/blog.txt new file mode 100644 index 0000000000..ffd04b2010 --- /dev/null +++ b/challenge-237/wlmb/blog.txt @@ -0,0 +1 @@ +https://wlmb.github.io/2023/10/01/PWC237/ diff --git a/challenge-237/wlmb/perl/ch-1.pl b/challenge-237/wlmb/perl/ch-1.pl new file mode 100755 index 0000000000..fb3ce06dc4 --- /dev/null +++ b/challenge-237/wlmb/perl/ch-1.pl @@ -0,0 +1,38 @@ +#!/usr/bin/env perl +# Perl weekly challenge 237 +# Task 1: Seize The Day +# +# See https://wlmb.github.io/2023/10/01/PWC237/#task-1-seize-the-day +use v5.36; +use experimental qw(for_list); +use PDL; +die <<~"FIN" unless @ARGV && @ARGV%4==0; + Usage: $0 Y1 M1 W1 D1 [Y2 M2 W2 D2...] + to find the number corresponding to day Dn of week (1=Monday), + weekday of month Wn, month Mn, year Yn + FIN +my $days_of_month=pdl[[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], # length of months + [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]]; # nonleap and leap +my $days_to_month=pdl[[0,3,3,6,1,4,6,2,5,0,3,5], # days to start of month nonleap and leap mod7 + [0,3,4,0,2,5,0,3,6,1,4,6]]; +my @ordinal=qw(first second third fourth fifth); +my @day_name=qw(Sunday Monday Tuesday Wednesday Thursday Friday Saturday); +my @month_name=qw(January February March April May June + July August September October November Dececmber); +for my($year, $month, $weekday, $day_of_week) (@ARGV){ + warn "Weekday should be between 1 and 5: $weekday", next unless 1<=$weekday<=5; + warn "Day of week should be between 1 (Mon) and 7 (Sun): $day_of_week", next + unless 1<=$day_of_week<=7; + warn "Month should be between 1 and 12", next unless 1<=$month<=12; + --$_ for $weekday, $month; # start at 0 + $day_of_week%=7; # Sun is now 0 + my $reduced_year=$year%400; # Cycle repeats after 400 years + my $previous_leaps=(floor(($reduced_year+3)/4) + -floor(($reduced_year+3)/100))%7; # Leap years before start of given year + my $start=($reduced_year+$previous_leaps+6)%7; # starting day of week of year, counting from sunday==0 + my $given_is_leap=($reduced_year==0 || ($reduced_year%100!=0 && $reduced_year%4==0))||0; + my $beggining=($days_to_month->at($month, $given_is_leap)+$start)%7; # first day of week of month + my $day=1+($day_of_week-$beggining)%7+$weekday*7; # desired date + $day=0 if $day>$days_of_month->at($month,$given_is_leap); # check it lies within month + say "The $ordinal[$weekday] $day_name[$day_of_week] of $month_name[$month] in $year is $day"; +} diff --git a/challenge-237/wlmb/perl/ch-2.pl b/challenge-237/wlmb/perl/ch-2.pl new file mode 100755 index 0000000000..3fda9ef510 --- /dev/null +++ b/challenge-237/wlmb/perl/ch-2.pl @@ -0,0 +1,18 @@ +#!/usr/bin/env perl +# Perl weekly challenge 237 +# Task 2: Maximise Greatness +# +# See https://wlmb.github.io/2023/10/01/PWC237/#task-2-maximise-greatness +use v5.36; +die <<~"FIN" unless @ARGV; + Usage: $0 N1 [N2...] + to find the greatness of the array N1 N2... + FIN +my @copy=my @sorted=sort {$a<=>$b} @ARGV; +my $current=shift @sorted; +my @permutation; +while(@copy){ + my $next=shift @copy; + push(@permutation, $next), $current=shift @sorted if $current<$next +} +say "@ARGV -> ", 0+@permutation; -- cgit From b3a348402571426fd9a47a344fcbf3f8e83859a2 Mon Sep 17 00:00:00 2001 From: pme Date: Mon, 2 Oct 2023 20:32:39 +0200 Subject: challenge-237 --- challenge-237/peter-meszaros/perl/ch-1.pl | 61 ++++++++++++++++++++++++++++ challenge-237/peter-meszaros/perl/ch-2.pl | 66 +++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100755 challenge-237/peter-meszaros/perl/ch-1.pl create mode 100755 challenge-237/peter-meszaros/perl/ch-2.pl diff --git a/challenge-237/peter-meszaros/perl/ch-1.pl b/challenge-237/peter-meszaros/perl/ch-1.pl new file mode 100755 index 0000000000..4cbda65aa0 --- /dev/null +++ b/challenge-237/peter-meszaros/perl/ch-1.pl @@ -0,0 +1,61 @@ +#!/usr/bin/env perl +# +# Given a year, a month, a weekday of month, and a day of week (1 (Mon) .. 7 +# (Sun)), print the day. +# +# Example 1 +# +# Input: Year = 2024, Month = 4, Weekday of month = 3, day of week = 2 +# Output: 16 +# +# The 3rd Tue of Apr 2024 is the 16th +# +# Example 2 +# +# Input: Year = 2025, Month = 10, Weekday of month = 2, day of week = 4 +# Output: 9 +# +# The 2nd Thu of Oct 2025 is the 9th +# +# Example 3 +# +# Input: Year = 2026, Month = 8, Weekday of month = 5, day of week = 3 +# Output: 0 +# +# There isn't a 5th Wed in Aug 2026 +# + +use strict; +use warnings; +use Test::More; +use Data::Dumper; +use Date::Calc qw/Nth_Weekday_of_Month_Year/; + +my $cases = [ + # Year, Month, Weekday of month, day of week + [ 2024, 4, 3, 2], + [ 2025, 10, 2, 4], + [ 2026, 8, 5, 3], +]; + +sub seize_the_day +{ + my $l = shift; + + my (undef, undef, $day) = + Nth_Weekday_of_Month_Year($l->[0], + $l->[1], + $l->[3], + $l->[2]); + + return $day // 0; +} + +is(seize_the_day($cases->[0]), 16, '[ 2024, 4, 3, 2]'); +is(seize_the_day($cases->[1]), 9, '[ 2025, 10, 2, 4]'); +is(seize_the_day($cases->[2]), 0, '[ 2026, 8, 5, 3]'); +done_testing(); + +exit 0; + + diff --git a/challenge-237/peter-meszaros/perl/ch-2.pl b/challenge-237/peter-meszaros/perl/ch-2.pl new file mode 100755 index 0000000000..573e51bbe9 --- /dev/null +++ b/challenge-237/peter-meszaros/perl/ch-2.pl @@ -0,0 +1,66 @@ +#!/usr/bin/env perl +# +# You are given an array of integers. +# +# Write a script to permute the give array such that you get the maximum +# possible greatness. +# +# To determine greatness, nums[i] < perm[i] where 0 <= i < nums.length +# +# +# Example 1 +# +# Input: @nums = (1, 3, 5, 2, 1, 3, 1) +# Output: 4 +# +# One possible permutation: (2, 5, 1, 3, 3, 1, 1) which returns 4 greatness as +# below: +# nums[0] < perm[0] +# nums[1] < perm[1] +# nums[3] < perm[3] +# nums[4] < perm[4] +# +# Example 2 +# +# Input: @ints = (1, 2, 3, 4) +# Output: 3 +# +# One possible permutation: (2, 3, 4, 1) which returns 3 greatness as below: +# nums[0] < perm[0] +# nums[1] < perm[1] +# nums[2] < perm[2] +# + +use strict; +use warnings; +use Test::More; +use Data::Dumper; +use Math::Combinatorics qw/permute/; + +my $cases = [ + [1, 3, 5, 2, 1, 3, 1], + [1, 2, 3, 4], +]; + +sub maximise_greatness +{ + my $l = shift; + + my $maxperm = 0; + + for my $p (permute(@$l)) { + my $perm = 0; + for (my $i=0; $i < @$p; ++$i) { + ++$perm if $p->[$i] > $l->[$i]; + } + $maxperm = $perm if $perm > $maxperm; + } + + return $maxperm; +} + +is(maximise_greatness($cases->[0]), 4, '[1, 3, 5, 2, 1, 3, 1]'); +is(maximise_greatness($cases->[1]), 3, '[1, 2, 3, 4]'); +done_testing(); + +exit 0; -- cgit From b651d3e2450edeeb41386d2c7ebaf954394546db Mon Sep 17 00:00:00 2001 From: "E. Choroba" Date: Mon, 2 Oct 2023 22:57:39 +0200 Subject: Solve 237: Seize the Day & Maximise Greatness by E. Choroba --- challenge-237/e-choroba/perl/ch-1.pl | 59 +++++++++++++++++++++++++++++++++ challenge-237/e-choroba/perl/ch-2.pl | 63 ++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100755 challenge-237/e-choroba/perl/ch-1.pl create mode 100755 challenge-237/e-choroba/perl/ch-2.pl diff --git a/challenge-237/e-choroba/perl/ch-1.pl b/challenge-237/e-choroba/perl/ch-1.pl new file mode 100755 index 0000000000..4d53d02709 --- /dev/null +++ b/challenge-237/e-choroba/perl/ch-1.pl @@ -0,0 +1,59 @@ +#!/usr/bin/perl +use warnings; +use strict; +use experimental qw( signatures ); + +use Time::Piece; +use Time::Seconds qw{ ONE_DAY ONE_WEEK }; + +sub seize_the_day($year, $month, $weekday_of_month, $day_of_week) { + return 0 if $weekday_of_month > 5; + + # In the input, 1 is Monday, 7 is Sunday. + $day_of_week = ((1 + $day_of_week) % 7) || 7; + + my $tp = 'Time::Piece'->strptime(sprintf('%04d%02d%02d', $year, $month, 1), + '%Y%m%d'); + my $weekday = $tp->wday; + $tp += ONE_DAY * (($day_of_week - $weekday) % 7); # The expected weekday. + $tp += ONE_WEEK * ($weekday_of_month - 1); # The expected week. + return $tp->mon == $month ? $tp->mday : 0 +} + +use Test::More tests => 3 + 26; + +is seize_the_day(2024, 4, 3, 2), 16, + 'Example 1 # The 3rd Tue of Apr 2024 is the 16th'; +is seize_the_day(2025, 10, 2, 4), 9, + 'Example 2 # The 2nd Thu of Oct 2025 is the 9th'; +is seize_the_day(2026, 8, 5, 3), 0, + "Example 3 # There isn't a 5th Wed in Aug 2026"; + +is seize_the_day(2023, 1, 53, 1), 0, '53 weeks in a year'; + +is seize_the_day(2023, 10, 1, 1), 2, 'Mon Oct 2 2023'; +is seize_the_day(2023, 10, 1, 2), 3, 'Tue Oct 3 2023'; +is seize_the_day(2023, 10, 1, 3), 4, 'Tue Oct 4 2023'; +is seize_the_day(2023, 10, 1, 4), 5, 'Tue Oct 5 2023'; +is seize_the_day(2023, 10, 1, 5), 6, 'Tue Oct 6 2023'; +is seize_the_day(2023, 10, 1, 6), 7, 'Tue Oct 7 2023'; +is seize_the_day(2023, 10, 1, 7), 1, 'Sun Oct 1 2023'; +is seize_the_day(2023, 10, 2, 1), 9, 'Mon Oct 9 2023'; +is seize_the_day(2023, 10, 2, 7), 8, 'Sun Oct 8 2023'; +is seize_the_day(2023, 10, 5, 1), 30, 'Mon Oct 30 2023'; +is seize_the_day(2023, 10, 5, 2), 31, 'Tue Oct 31 2023'; +is seize_the_day(2023, 10, 5, 7), 29, 'Sun Oct 29 2023'; + +is seize_the_day(2023, 12, 1, 1), 4, 'Mon Dec 4 2023'; +is seize_the_day(2023, 12, 1, 2), 5, 'Tue Dec 5 2023'; +is seize_the_day(2023, 12, 1, 3), 6, 'Wed Dec 6 2023'; +is seize_the_day(2023, 12, 1, 4), 7, 'Thu Dec 7 2023'; +is seize_the_day(2023, 12, 1, 5), 1, 'Fri Dec 1 2023'; +is seize_the_day(2023, 12, 1, 6), 2, 'Sat Dec 2 2023'; +is seize_the_day(2023, 12, 1, 7), 3, 'Sun Dec 3 2023'; +is seize_the_day(2023, 12, 2, 1), 11, 'Mon Dec 11 2023'; +is seize_the_day(2023, 12, 2, 5), 8, 'Fri Dec 8 2023'; +is seize_the_day(2023, 12, 4, 4), 28, 'Thu Dec 28 2023'; +is seize_the_day(2023, 12, 5, 6), 30, 'Sat Dec 30 2023'; +is seize_the_day(2023, 12, 5, 7), 31, 'Sun Dec 31 2023'; +is seize_the_day(2023, 12, 5, 1), 0, '4 Mondays in Dec 2023'; diff --git a/challenge-237/e-choroba/perl/ch-2.pl b/challenge-237/e-choroba/perl/ch-2.pl new file mode 100755 index 0000000000..80c6e835c2 --- /dev/null +++ b/challenge-237/e-choroba/perl/ch-2.pl @@ -0,0 +1,63 @@ +#!/usr/bin/perl +use warnings; +use strict; +use experimental qw( signatures ); + +sub maximise_greatness(@nums) { + my @sorted = sort { $a <=> $b } @nums; + + # No greatness at all. + return 0 if $sorted[0] == $sorted[-1]; + + my $count = 0; + my $less = 0; + my $greater = 1; + while (1) { + ++$greater while $greater <= $#sorted + && $sorted[$greater] == $sorted[$less]; + last if $greater > $#sorted; + + ++$count if $sorted[$less++] < $sorted[$greater++]; + last if $greater > $#sorted; + } + return $count +} + +use Algorithm::Combinatorics qw{ permutations }; +sub maximise_greatness_brute_force(@nums) { + my $iter = permutations(\@nums); + my $max_count = 0; + while (my $p = $iter->next) { + my $count = grep $nums[$_] < $p->[$_], 0 .. $#nums; + $max_count = $count if $count > $max_count; + } + return $max_count +} + +use Test::More tests => 2 * (2 + 4) + 1; + +for my $maximise_greatness ( + \&maximise_greatness, \&maximise_greatness_brute_force +) { + + is $maximise_greatness->(1, 3, 5, 2, 1, 3, 1), 4, 'Example 1'; + is $maximise_greatness->(1, 2, 3, 4), 3, 'Example 2'; + + is $maximise_greatness->(1, 1, 1), 0, 'Not great'; + is $maximise_greatness->(1, 1, 2, 2, 2), 2, 'More of the greater ones'; + is $maximise_greatness->(1, 1, 1, 2, 2), 2, 'More of the less ones'; + is $maximise_greatness->(1, 2, 2, 2, 3), 2, 'More of the middle ones'; +} + +use Benchmark qw{ cmpthese }; +my @l = map int rand 7, 1 .. 8; +is maximise_greatness(@l), maximise_greatness_brute_force(@l), "same @l"; +cmpthese(-3, { + brute_force => sub { maximise_greatness_brute_force(@l) }, + optimised => sub { maximise_greatness(@l) }, +}); + +__END__ + Rate brute_force optimised +brute_force 8.74/s -- -100% +optimised 210776/s 2412117% -- -- cgit From 3ef6bb41dfa131467507f1de256dfa0ddd839bf1 Mon Sep 17 00:00:00 2001 From: Mark <53903062+andemark@users.noreply.github.com> Date: Tue, 3 Oct 2023 01:30:25 +0000 Subject: Challenge 237 Solutions (Raku) --- challenge-237/mark-anderson/raku/WDOM.rakumod | 28 +++++++++++++++++++++++++++ challenge-237/mark-anderson/raku/ch-1.raku | 13 +++++++++++++ challenge-237/mark-anderson/raku/ch-2.raku | 21 ++++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 challenge-237/mark-anderson/raku/WDOM.rakumod create mode 100644 challenge-237/mark-anderson/raku/ch-1.raku create mode 100644 challenge-237/mark-anderson/raku/ch-2.raku diff --git a/challenge-237/mark-anderson/raku/WDOM.rakumod b/challenge-237/mark-anderson/raku/WDOM.rakumod new file mode 100644 index 0000000000..8e96b4b280 --- /dev/null +++ b/challenge-237/mark-anderson/raku/WDOM.rakumod @@ -0,0 +1,28 @@ +unit class WDOM is Date is export; + +multi method new(:$weekday-of-month!, :$day-of-week!, :$month!, :$year! where $weekday-of-month eq 'L'|'Last') +{ + my $dt = Date.new(:$year, :$month).last-date-in-month; + my $d = $dt.day-of-week - $day-of-week; + $dt - ($d >= 0 ?? $d !! 7 + $d) +} + +multi method new(:$weekday-of-month!, :$day-of-week!, :$month!, :$year! where $weekday-of-month ~~ 1..4) +{ + my $dt = Date.new(:$year, :$month); + my $wdom = $day-of-week >= $dt.day-of-week ?? $weekday-of-month - 1 + !! $weekday-of-month; + $dt += 7 * $wdom + $day-of-week - $dt.day-of-week +} + +multi method new(:$weekday-of-month!, :$day-of-week!, :$month!, :$year! where $weekday-of-month == 5) +{ + my $dt = Date.new(:$year, :$month).last-date-in-month; + my $d = $dt.day-of-week - $day-of-week; + $dt -= $d >= 0 ?? $d !! 7 + $d; + + return $dt if $dt.day == 29|30|31; + + # Todo: Handle the exception here. Just return the 4th day-of-week? + die "There isn't a 5th $day-of-week in $month $year" +} diff --git a/challenge-237/mark-anderson/raku/ch-1.raku b/challenge-237/mark-anderson/raku/ch-1.raku new file mode 100644 index 0000000000..760b1a5807 --- /dev/null +++ b/challenge-237/mark-anderson/raku/ch-1.raku @@ -0,0 +1,13 @@ +#!/usr/bin/env raku +use lib '.'; +use WDOM; +use Test; + +is seize-the-day(2024, 4, 3, 2), 16; +is seize-the-day(2025, 10, 2, 4), 9; +is seize-the-day(2026, 8, 5, 3), 0; + +sub seize-the-day($year, $month, $weekday-of-month, $day-of-week) +{ + quietly + try WDOM.new(:$weekday-of-month, :$day-of-week, :$month, :$year).day +} diff --git a/challenge-237/mark-anderson/raku/ch-2.raku b/challenge-237/mark-anderson/raku/ch-2.raku new file mode 100644 index 0000000000..875abf6529 --- /dev/null +++ b/challenge-237/mark-anderson/raku/ch-2.raku @@ -0,0 +1,21 @@ +#!/usr/bin/env raku +use Test; + +is maximise-greatness(1,3,5,2,1,3,1), 4; +is maximise-greatness(1,2,3,4), 3; +is maximise-greatness(1,3,5,2,1,3,1,5), 5; +is maximise-greatness(4,5,5,5,5), 1; +is maximise-greatness(3,3,3,3,3), 0; + +sub maximise-greatness(*@n) +{ + @n .= sort; + my $i = 0; + + sum do while @n[0] < @n[*-1] and $i < @n + { + $i++ while @n[0] == @n[$i]; + @n.shift; + 1 + } +} -- cgit From 98b832f1ff2919defd3e4fa528b60362a6caf0fc Mon Sep 17 00:00:00 2001 From: Michael Firkins Date: Mon, 2 Oct 2023 21:05:31 +1100 Subject: pwc237 solution in python --- challenge-237/pokgopun/python/ch-1.py | 55 +++++++++++++++++++++++++++++++ challenge-237/pokgopun/python/ch-2.py | 62 +++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 challenge-237/pokgopun/python/ch-1.py create mode 100644 challenge-237/pokgopun/python/ch-2.py diff --git a/challenge-237/pokgopun/python/ch-1.py b/challenge-237/pokgopun/python/ch-1.py new file mode 100644 index 0000000000..e04ed8c727 --- /dev/null +++ b/challenge-237/pokgopun/python/ch-1.py @@ -0,0 +1,55 @@ +### https://theweeklychallenge.org/blog/perl-weekly-challenge-237/ +""" + +Task 1: Seize The Day + +Submitted by: [44]Mark Anderson + __________________________________________________________________ + + Given a year, a month, a weekday of month, and a day of week (1 (Mon) + .. 7 (Sun)), print the day. + +Example 1 + +Input: Year = 2024, Month = 4, Weekday of month = 3, day of week = 2 +Output: 16 + +The 3rd Tue of Apr 2024 is the 16th + +Example 2 + +Input: Year = 2025, Month = 10, Weekday of month = 2, day of week = 4 +Output: 9 + +The 2nd Thu of Oct 2025 is the 9th + +Example 3 + +Input: Year = 2026, Month = 8, Weekday of month = 5, day of week = 3 +Output: 0 + +There isn't a 5th Wed in Aug 2026 + +Task 2: Maximise Greatness +""" +### solution by pokgopun@gmail.com + +import datetime + +def seizeTheDay(tup): + y,m,mw,wd = tup + dt = datetime.date(y, m, 1) + wdd = wd - dt.isoweekday() + if wdd < 0: wdd += 7 + try: + return dt.replace(day = 1 + 7*(mw - 1) + wdd).day + except: + return 0 + +for inpt,otpt in { + (2024,4,3,2): 16, + (2025,10,2,4): 9, + (2026,8,5,3): 0, + }.items(): + print(seizeTheDay(inpt)==otpt) + diff --git a/challenge-237/pokgopun/python/ch-2.py b/challenge-237/pokgopun/python/ch-2.py new file mode 100644 index 0000000000..7f52133712 --- /dev/null +++ b/challenge-237/pokgopun/python/ch-2.py @@ -0,0 +1,62 @@ +### https://theweeklychallenge.org/blog/perl-weekly-challenge-237/ +""" + +Task 2: Maximise Greatness + +Submitted by: [45]Mohammad S Anwar + __________________________________________________________________ + + You are given an array of integers. + + Write a script to permute the give array such that you get the maximum + possible greatness. + + To determine greatness, nums[i] < perm[i] where 0 <= i < nums.length + +Example 1 + +Input: @nums = (1, 3, 5, 2, 1, 3, 1) +Output: 4 + +One possible permutation: (2, 5, 1, 3, 3, 1, 1) which returns 4 greatness as bel +ow: +nums[0] < perm[0] +nums[1] < perm[1] +nums[3] < perm[3] +nums[4] < perm[4] + +Example 2 + +Input: @ints = (1, 2, 3, 4) +Output: 3 + +One possible permutation: (2, 3, 4, 1) which returns 3 greatness as below: +nums[0] < perm[0] +nums[1] < perm[1] +nums[2] < perm[2] + __________________________________________________________________ + + Last date to submit the solution 23:59 (UK Time) Sunday 8th October + 2023. + __________________________________________________________________ + +SO WHAT DO YOU THINK ? +""" +### solution by pokgopun@gmail.com + +from itertools import permutations + +def maxGreat(tup): + l, m = len(tup), 0 + for pm in permutations(tup): + g = tuple( pm[i] > tup[i] for i in range(l) ).count(True) + if m < g : m = g + return m + +for inpt,otpt in { + (1, 3, 5, 2, 1, 3, 1): 4, + (1, 2, 3, 4): 3, + }.items(): + print(maxGreat(inpt)==otpt) + + -- cgit From 97f2d015bd33e12ea9c82aa5d64e7a3893e9b7ea Mon Sep 17 00:00:00 2001 From: Michael Firkins Date: Tue, 3 Oct 2023 13:49:11 +1100 Subject: pwc237 solution in go --- challenge-237/pokgopun/go/ch-1.go | 74 +++++++++++++++++++++++++++ challenge-237/pokgopun/go/ch-2.go | 103 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 challenge-237/pokgopun/go/ch-1.go create mode 100644 challenge-237/pokgopun/go/ch-2.go diff --git a/challenge-237/pokgopun/go/ch-1.go b/challenge-237/pokgopun/go/ch-1.go new file mode 100644 index 0000000000..df3cd16249 --- /dev/null +++ b/challenge-237/pokgopun/go/ch-1.go @@ -0,0 +1,74 @@ +//# https://theweeklychallenge.org/blog/perl-weekly-challenge-237/ +/*# + +Task 1: Seize The Day + +Submitted by: [44]Mark Anderson + __________________________________________________________________ + + Given a year, a month, a weekday of month, and a day of week (1 (Mon) + .. 7 (Sun)), print the day. + +Example 1 + +Input: Year = 2024, Month = 4, Weekday of month = 3, day of week = 2 +Output: 16 + +The 3rd Tue of Apr 2024 is the 16th + +Example 2 + +Input: Year = 2025, Month = 10, Weekday of month = 2, day of week = 4 +Output: 9 + +The 2nd Thu of Oct 2025 is the 9th + +Example 3 + +Input: Year = 2026, Month = 8, Weekday of month = 5, day of week = 3 +Output: 0 + +There isn't a 5th Wed in Aug 2026 + +Task 2: Maximise Greatness +#*/ +//# solution by pokgopun@gmail.com + +package main + +import ( + "fmt" + "time" +) + +func main() { + for _, data := range []struct { + mDate mDate + output int + }{ + {mDate{2024, 4, 3, 2}, 16}, + {mDate{2025, 10, 2, 4}, 9}, + {mDate{2026, 8, 5, 3}, 0}, + } { + fmt.Println(data.mDate.day() == data.output) + } +} + +type mDate struct { + y int + m time.Month + mw, wd int +} + +func (md mDate) day() int { + d := time.Date(md.y, md.m, 1, 0, 0, 0, 0, time.UTC) + wdd := (md.wd % 7) - int(d.Weekday()) + if wdd < 0 { + wdd += 7 + } + d = d.AddDate(0, 0, 7*(md.mw-1)+wdd) + if d.Month() != md.m { + return 0 + } + return d.Day() +} diff --git a/challenge-237/pokgopun/go/ch-2.go b/challenge-237/pokgopun/go/ch-2.go new file mode 100644 index 0000000000..fc9c652ddd --- /dev/null +++ b/challenge-237/pokgopun/go/ch-2.go @@ -0,0 +1,103 @@ +//# https://theweeklychallenge.org/blog/perl-weekly-challenge-237/ +/*# + +Task 2: Maximise Greatness + +Submitted by: [45]Mohammad S Anwar + __________________________________________________________________ + + You are given an array of integers. + + Write a script to permute the give array such that you get the maximum + possible greatness. + + To determine greatness, nums[i] < perm[i] where 0 <= i < nums.length + +Example 1 + +Input: @nums = (1, 3, 5, 2, 1, 3, 1) +Output: 4 + +One possible permutation: (2, 5, 1, 3, 3, 1, 1) which returns 4 greatness as bel +ow: +nums[0] < perm[0] +nums[1] < perm[1] +nums[3] < perm[3] +nums[4] < perm[4] + +Example 2 + +Input: @ints = (1, 2, 3, 4) +Output: 3 + +One possible permutation: (2, 3, 4, 1) which returns 3 greatness as below: +nums[0] < perm[0] +nums[1] < perm[1] +nums[2] < perm[2] + __________________________________________________________________ + + Last date to submit the solution 23:59 (UK Time) Sunday 8th October + 2023. + __________________________________________________________________ + +SO WHAT DO YOU THINK ? +#*/ +//# solution by pokgopun@gmail.com + +package main + +import "fmt" + +func main() { + for _, data := range []struct { + input []int + output uint + }{ + {[]int{1, 3, 5, 2, 1, 3, 1}, 4}, + {[]int{1, 2, 3, 4}, 3}, + } { + fmt.Println(mySlice(data.input).maxGreat() == data.output) + } +} + +type mySlice []int + +func (ms mySlice) maxGreat() uint { + n := uint(len(ms)) + fact := uint(1) + for i := n; i > 1; i-- { + fact *= i + } + var g, mg uint + for r := uint(0); r < fact; r++ { + g = ms.great(n, r, fact) + if mg < g { + mg = g + } + } + return mg +} + +func (ms mySlice) great(n, r, fact uint) (g uint) { + if r > fact-1 { + return 0 + } + fact /= n + digits := make([]uint, uint(n)) + for i := uint(0); i < n; i++ { + digits[i] = i + } + var q uint + for i := uint(0); i < n; i++ { + q = r / fact + r %= fact + if ms[digits[q]] > ms[i] { + g++ + } + copy(digits[q:], digits[q+1:]) + if i != n-1 { + fact /= n - 1 - i + } + } + return g +} -- cgit From d4fc50b416f73f6983f31249bded770d03d3d6f3 Mon Sep 17 00:00:00 2001 From: Luis Mochan Date: Mon, 2 Oct 2023 23:04:37 -0600 Subject: Solve T1 without PDL --- challenge-237/wlmb/perl/ch-1.pl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/challenge-237/wlmb/perl/ch-1.pl b/challenge-237/wlmb/perl/ch-1.pl index fb3ce06dc4..5b15cafa5a 100755 --- a/challenge-237/wlmb/perl/ch-1.pl +++ b/challenge-237/wlmb/perl/ch-1.pl @@ -5,34 +5,34 @@ # See https://wlmb.github.io/2023/10/01/PWC237/#task-1-seize-the-day use v5.36; use experimental qw(for_list); -use PDL; +use POSIX qw(floor); die <<~"FIN" unless @ARGV && @ARGV%4==0; Usage: $0 Y1 M1 W1 D1 [Y2 M2 W2 D2...] to find the number corresponding to day Dn of week (1=Monday), weekday of month Wn, month Mn, year Yn FIN -my $days_of_month=pdl[[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], # length of months - [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]]; # nonleap and leap -my $days_to_month=pdl[[0,3,3,6,1,4,6,2,5,0,3,5], # days to start of month nonleap and leap mod7 - [0,3,4,0,2,5,0,3,6,1,4,6]]; +my @days_of_month=([31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], # length of months + [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]); # nonleap and leap +my @days_to_month=([0,3,3,6,1,4,6,2,5,0,3,5], # days to start of month nonleap and leap mod7 + [0,3,4,0,2,5,0,3,6,1,4,6]); my @ordinal=qw(first second third fourth fifth); my @day_name=qw(Sunday Monday Tuesday Wednesday Thursday Friday Saturday); my @month_name=qw(January February March April May June - July August September October November Dececmber); + July August September October November Dececmber); for my($year, $month, $weekday, $day_of_week) (@ARGV){ warn "Weekday should be between 1 and 5: $weekday", next unless 1<=$weekday<=5; warn "Day of week should be between 1 (Mon) and 7 (Sun): $day_of_week", next - unless 1<=$day_of_week<=7; + unless 1<=$day_of_week<=7; warn "Month should be between 1 and 12", next unless 1<=$month<=12; --$_ for $weekday, $month; # start at 0 $day_of_week%=7; # Sun is now 0 my $reduced_year=$year%400; # Cycle repeats after 400 years my $previous_leaps=(floor(($reduced_year+3)/4) - -floor(($reduced_year+3)/100))%7; # Leap years before start of given year + -floor(($reduced_year+3)/100))%7; # Leap years before start of given year my $start=($reduced_year+$previous_leaps+6)%7; # starting day of week of year, counting from sunday==0 my $given_is_leap=($reduced_year==0 || ($reduced_year%100!=0 && $reduced_year%4==0))||0; - my $beggining=($days_to_month->at($month, $given_is_leap)+$start)%7; # first day of week of month + my $beggining=($days_to_month[$given_is_leap][$month]+$start)%7; # first day of week of month my $day=1+($day_of_week-$beggining)%7+$weekday*7; # desired date - $day=0 if $day>$days_of_month->at($month,$given_is_leap); # check it lies within month + $day=0 if $day>$days_of_month[$given_is_leap][$month]; # check it lies within month say "The $ordinal[$weekday] $day_name[$day_of_week] of $month_name[$month] in $year is $day"; } -- cgit From 93569fd42bd127196013fc5c872fd678fe26fdba Mon Sep 17 00:00:00 2001 From: Luca Ferrari Date: Mon, 2 Oct 2023 23:01:18 +0200 Subject: PWC 237 --- challenge-237/luca-ferrari/blog-1.txt | 1 + challenge-237/luca-ferrari/blog-2.txt | 1 + challenge-237/luca-ferrari/blog-3.txt | 1 + challenge-237/luca-ferrari/blog-4.txt | 1 + challenge-237/luca-ferrari/blog-5.txt | 1 + challenge-237/luca-ferrari/blog-6.txt | 1 + challenge-237/luca-ferrari/postgresql/ch-1.plperl | 42 +++++++++++++ challenge-237/luca-ferrari/postgresql/ch-1.sql | 76 +++++++++++++++++