From ea8f690dcd0eb4d25606d31f9fffd1d44f696a75 Mon Sep 17 00:00:00 2001 From: ntovar Date: Fri, 8 Mar 2024 19:03:58 -0500 Subject: Challenge 259. Add Perl and Bash solutions. By Nelo Tovar. --- challenge-259/nelo-tovar/bash/ch-1.sh | 47 ++++++++++++++++++++++++++++++ challenge-259/nelo-tovar/bash/ch-2.sh | 37 +++++++++++++++++++++++ challenge-259/nelo-tovar/perl/ch-1.pl | 55 +++++++++++++++++++++++++++++++++++ challenge-259/nelo-tovar/perl/ch-2.pl | 45 ++++++++++++++++++++++++++++ 4 files changed, 184 insertions(+) create mode 100755 challenge-259/nelo-tovar/bash/ch-1.sh create mode 100755 challenge-259/nelo-tovar/bash/ch-2.sh create mode 100644 challenge-259/nelo-tovar/perl/ch-1.pl create mode 100644 challenge-259/nelo-tovar/perl/ch-2.pl diff --git a/challenge-259/nelo-tovar/bash/ch-1.sh b/challenge-259/nelo-tovar/bash/ch-1.sh new file mode 100755 index 0000000000..1f360d6a59 --- /dev/null +++ b/challenge-259/nelo-tovar/bash/ch-1.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# +# The Weekly Challenge 259 - By Nelo Tovar +# +# https://theweeklychallenge.org/blog/perl-weekly-challenge-259/ +# +# Task 1 : Banking Day Offset + +function banking_day_offset() { + local date_offset=$1 + local offset=$2 + local bank_holidays=$3 + + for (( i = 1; i <= $offset; i++ )); do + date_offset=$(date +%Y-%m-%d -d "$date_offset + 1 day") + + while [[ $(date +%u -d $date_offset) =~ [67] ]]; do + date_offset=$(date +%Y-%m-%d -d "$date_offset + 1 day") + done + + if [[ $bank_holidays && "$date_offset" == *"$bank_holidays"* ]]; then + date_offset=$(date +%Y-%m-%d -d "$date_offset + 1 day") + fi + done + + echo $date_offset +} + +example=('2018-06-28' '2018-06-28') +example_offset=(3 3) +example_bank_holidays=('2018-07-03') + +for e in 0 1; do + start_date=${example[$e]} + offset=${example_offset[$e]} + bank_holidays=${example_bank_holidays[$e]} + + bdo=$(banking_day_offset "$start_date" $offset $bank_holidays) + echo -n "Input : start_date = $start_date, offset = $offset" + if [ $bank_holidays ]; then + echo -n ", bank_holidays = $bank_holidays" + fi + echo " " + echo "Output : $bdo" + echo "" +done + diff --git a/challenge-259/nelo-tovar/bash/ch-2.sh b/challenge-259/nelo-tovar/bash/ch-2.sh new file mode 100755 index 0000000000..cf8c4ab389 --- /dev/null +++ b/challenge-259/nelo-tovar/bash/ch-2.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# +# The Weekly Challenge 259 - By Nelo Tovar +# +# https://theweeklychallenge.org/blog/perl-weekly-challenge-259/ +# +# Task 2 : Line Parser + +function line_parser() { + local original_line=$1 + local line_parsed='{\n' + + if [[ "$original_line" =~ ^\{%[[:space:]]+([[:alpha:]]+)[[:space:]]+[[:alpha:]]+[[:space:]]* ]]; then + line_parsed+="\tname => ${BASH_REMATCH[1]}\n" + line_parsed+="\tfields => {\n" + + while [[ $original_line =~ ([[:alpha:]]+)=\"?([[:alnum:][:space:]\"\\]+) ]]; do + line_parsed+="\t\t${BASH_REMATCH[1]} => ${BASH_REMATCH[2]},\n" + original_line=${original_line/${BASH_REMATCH[1]}=/} + original_line=${original_line/${BASH_REMATCH[2]}/} + done + line_parsed+="\t}\n" + fi + line_parsed+='}' + echo $line_parsed +} + +examples=( + '{% youtube title="Title \"quoted\" done" %}' + '{% youtube title="Title with escaped backslash \\" %}' + ) + +for e in 0 1; do + lp=$(line_parser "${examples[$e]}") + echo -e "$lp" +done + diff --git a/challenge-259/nelo-tovar/perl/ch-1.pl b/challenge-259/nelo-tovar/perl/ch-1.pl new file mode 100644 index 0000000000..4c6221d76a --- /dev/null +++ b/challenge-259/nelo-tovar/perl/ch-1.pl @@ -0,0 +1,55 @@ +#!/usr/bin/env perl + +# The Weekly Challenge 259 - By Nelo Tovar +# +# https://theweeklychallenge.org/blog/perl-weekly-challenge-259/ +# +# Task 1 - Banking Day Offset +# + +use strict; +use warnings; +use v5.28; +use List::Util qw/any/; +use DateTime; +use Data::Dump qw(dump); + +my @examples = ( '2018-06-28', '2018-06-28' ); +my @examples_offset = ( 3, 3 ); +my @examples_bank_holidays = ( + ['2018-07-03'], +); + +sub banking_day_offset { + my ($start_date, $offset, $bank_holidays) = @_; + my $day_offset = DateTime->new( + year => substr($start_date, 0, 4), + month => substr($start_date, 5, 2), + day => substr($start_date, 8, 2) + ); + + for (my $i = 1; $i <= $offset; $i++) { + $day_offset->add(days => 1); + + $day_offset->add(days => 1) while ($day_offset->day_of_week =~ /[67]/); + + $day_offset->add(days => 1) if (any {$day_offset->ymd eq $_} @$bank_holidays); + + + } + + return $day_offset->ymd; +} + +for (my $i = 0; $i < scalar @examples; $i++) { + my $elements = $examples[$i]; + my $offset = defined $examples_offset[$i] ? $examples_offset[$i] : 0; + my $bank_holidays = defined $examples_bank_holidays[$i] ? $examples_bank_holidays[$i] : undef; + my $bdo = banking_day_offset $elements, $offset, $bank_holidays; + + print 'Input : $start_date = ', $elements, ', $offset = ', $offset; + print ', $bank_holidays = ', dump(@$bank_holidays) if (defined $bank_holidays); + print "\n"; + say 'Output : ', $bdo; + say ' '; +} diff --git a/challenge-259/nelo-tovar/perl/ch-2.pl b/challenge-259/nelo-tovar/perl/ch-2.pl new file mode 100644 index 0000000000..00172efcec --- /dev/null +++ b/challenge-259/nelo-tovar/perl/ch-2.pl @@ -0,0 +1,45 @@ +#!/usr/bin/env perl + +# The Weekly Challenge 259 - By Nelo Tovar +# +# https://theweeklychallenge.org/blog/perl-weekly-challenge-259/ +# +# Task 2 - Line Parser +# + +use strict; +use warnings; +use feature qw/say/; +use Data::Dump qw/dump/; + +my @examples = ( + '{% youtube title="Title \"quoted\" done" %}', + '{% youtube title="Title with escaped backslash \\" %}', +); + +sub line_parser { + my $original_line = shift; + my %line_parsed; + + if ( $original_line =~ /^{%\s+(\w+)(\s+.+)\s*%}/) { + $line_parsed{name} = $1; + + $original_line =~ s/\\"/\034/g; + + while ($original_line =~ /(\w+)="?(\d+|[\w\034\s]+)"?/cg) { + my $field_name = $1; + my $value = $2; + $value =~ s/\034/"/g; + $line_parsed{fields}->{$field_name} = $value; + } + } + + return \%line_parsed; +} + +for my $elements (@examples) { + my $lp = line_parser $elements; + + say dump($lp); + say ' '; +} -- cgit From 13f22d5c15b0eae547b4190fe1afab64143969c0 Mon Sep 17 00:00:00 2001 From: Michael Manring Date: Tue, 5 Mar 2024 02:15:10 +1100 Subject: pwc259 solution in python --- challenge-259/pokgopun/python/ch-1.py | 86 ++++++++++++++++++++++++ challenge-259/pokgopun/python/ch-2.py | 119 ++++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 challenge-259/pokgopun/python/ch-1.py create mode 100644 challenge-259/pokgopun/python/ch-2.py diff --git a/challenge-259/pokgopun/python/ch-1.py b/challenge-259/pokgopun/python/ch-1.py new file mode 100644 index 0000000000..ab2c06878e --- /dev/null +++ b/challenge-259/pokgopun/python/ch-1.py @@ -0,0 +1,86 @@ +### https://theweeklychallenge.org/blog/perl-weekly-challenge-259/ +""" + +Task 1: Banking Day Offset + +Submitted by: [42]Lee Johnson + __________________________________________________________________ + + You are given a start date and offset counter. Optionally you also get + bank holiday date list. + + Given a number (of days) and a start date, return the number (of days) + adjusted to take into account non-banking days. In other words: convert + a banking day offset to a calendar day offset. + + Non-banking days are: +a) Weekends +b) Bank holidays + +Example 1 + +Input: $start_date = '2018-06-28', $offset = 3, $bank_holidays = ['2018-07-03'] +Output: '2018-07-04' + +Thursday bumped to Wednesday (3 day offset, with Monday a bank holiday) + +Example 2 + +Input: $start_date = '2018-06-28', $offset = 3 +Output: '2018-07-03' + +Task 2: Line Parser +""" +### solution by pokgopun@gmail.com + +from datetime import date,datetime,timedelta + +def str2date(datestr: str): ### convert date string to date object + return datetime.strptime(datestr,"%Y-%m-%d").date() + +def isWeekday(d: date): ### check if date object is a weekday, that is less than Saturday (i.e. 5 in python) + return d.weekday() < 5 + +def BDO(start: str, ofst: int, hols: tuple = ()): + dstart = str2date(start) + if isWeekday(dstart) == False: ### if startdate is a weekend day, move back to last friday + dstart -= timedelta(days = dstart.weekday() - 4) ### move back number of day from friday + + ### convert weekday offset (ofst) to everyday offset (dur), that is 7 * number of week (i.e. ofset // 5) and the remaing partial-weekday offset (ofst % 5) + dur = timedelta(days = 7*(ofst // 5) + ofst % 5) + ### now we need to account for partial-weekday offset in the everyday offset + if dstart.weekday() + ofst % 5 > 4: ### if partial-weekday offset move startdate over the current weekday, add weekend offset to everyday offset + dur += timedelta(days=2) + dend = dstart + dur ### calculate enddate + + ### now account for holidays one by one, need to start from the earliest holiday first so we sort holidays before processing + for hol in sorted(set(hols)): + dhol = str2date(hol) + if dhol > dstart and dhol <= dend and isWeekday(dhol): ### only offset holiday if it is a weekday and is later than startdate but not later than current enddate + dend += timedelta(days=1) + if isWeekday(dend) == False: ### if a holiday offset move enddate to a weekend day, add weekend offset + dend += timedelta(days=2) ### this is ok as we account for holiday offset one by one + return dend.strftime("%Y-%m-%d") + +import unittest + +class TestBDO(unittest.TestCase): + def test(self): + for output, (start_date, offset, bank_holidays) in { + "2018-07-04": ("2018-06-28", 3, ("2018-07-03",)), + "2018-07-03": ("2018-06-28", 3, ()), + "2018-07-05": ("2018-06-28", 3, ("2018-07-02", "2018-07-03")), + "2018-07-05": ("2018-06-28", 3, ("2018-07-06", "2018-07-03", "2018-07-02")), + "2018-07-06": ("2018-06-28", 3, ("2018-07-02", "2018-07-03", "2018-07-05")), + "2018-07-06": ("2018-06-28", 3, ("2018-07-02", "2018-07-03", "2018-07-05","2024-03-05")), + "2018-07-06": ("2018-06-28", 3, ("2018-07-02", "2018-07-03", "2018-07-05","1979-07-09")), + "2018-07-13": ("2018-06-28", 8, ("2018-07-02", "2018-07-03", "2018-07-05","1979-07-09")), + "2018-07-16": ("2018-06-28", 9, ("2018-07-02", "2018-07-03", "2018-07-05","1979-07-09")), + "2018-07-23": ("2018-06-28", 14, ("2018-07-02", "2018-07-03", "2018-07-05","1979-07-09")), + "2018-07-25": ("2018-06-28", 14, ("2018-07-02", "2018-07-03", "2018-07-05","2018-07-11","2018-07-18")), + "2018-07-05": ("2018-06-29", 3, ("2018-07-03",)), + "2018-07-05": ("2018-06-30", 3, ("2018-07-03",)), + }.items(): + self.assertEqual(output, BDO(start_date, offset, bank_holidays)) + +unittest.main() diff --git a/challenge-259/pokgopun/python/ch-2.py b/challenge-259/pokgopun/python/ch-2.py new file mode 100644 index 0000000000..ac56114e24 --- /dev/null +++ b/challenge-259/pokgopun/python/ch-2.py @@ -0,0 +1,119 @@ +### https://theweeklychallenge.org/blog/perl-weekly-challenge-259/ +""" + +Task 2: Line Parser + +Submitted by: [43]Gabor Szabo + __________________________________________________________________ + + You are given a line like below: +{% id field1="value1" field2="value2" field3=42 %} + + Where +a) "id" can be \w+. +b) There can be 0 or more field-value pairs. +c) The name of the fields are \w+. +b) The values are either number in which case we don't need parentheses or strin +g in + which case we need parentheses around them. + + The line parser should return structure like below: +{ + name => id, + fields => { + field1 => value1, + field2 => value2, + field3 => value3, + } +} + + It should be able to parse the following edge cases too: +{% youtube title="Title \"quoted\" done" %} + + and +{% youtube title="Title with escaped backslash \\" %} + + BONUS: Extend it to be able to handle multiline tags: +{% id filed1="value1" ... %} +LINES +{% endid %} + + You should expect the following structure from your line parser: +{ + name => id, + fields => { + field1 => value1, + field2 => value2, + field3 => value3, + } + text => LINES +} + __________________________________________________________________ + + Last date to submit the solution 23:59 (UK Time) Sunday 10th March + 2024. + __________________________________________________________________ + +SO WHAT DO YOU THINK ? +""" +### solution by pokgopun@gmail.com + +import re + +rgxLine = re.compile(r'{%\s(?P\w+)(?P(?:\s\w+=(?:\d+|"(?:\\(?:"|\\)|[^"\\])+?"))+)?\s%}(?:\n(?P[\d\D]+?)\n\{%\sendid\s%})?') +rgxKV = re.compile(r'\s(?P\w+)=(?P\d+|"(?:\\(?:"|\\)|[^"\\])+?")') + +def lineParser(msg: str): + res = rgxLine.match(msg) + parsed = { "name": res.group("name") } + resKV = res.group("kv") + if resKV is not None: + parsed["fields"] = {} + for resKV in rgxKV.finditer(res.group("kv")): + k = resKV.group("key") + v = resKV.group("value") + if v.isnumeric(): + v = int(v) + else: + v = v[1:-1].encode("utf-8").decode('unicode_escape') + parsed["fields"][k] = v + tag = res.group("tag") + if tag is not None: + parsed["text"] = tag + return parsed + +import unittest + +class TestLineParser(unittest.TestCase): + def test(self): + for inpt, otpt in { + r'{% youtube id=1234 title="Title \"quoted\" done" %}': { + 'name': 'youtube', + 'fields': { + 'id': 1234, + 'title': 'Title "quoted" done', + }, + }, + r'{% youtube title="Title with escaped backslash \\" id=4321 %}': { + 'name': 'youtube', + 'fields': { + 'id': 4321, + 'title': 'Title with escaped backslash \\', + }, + }, + r'''{% id field1="value1" field2=1324 %} +LINE1 +LINE2 +{% endid %}''': { + 'name': 'id', + 'fields': { + 'field2': 1324, + 'field1': 'value1', + }, + 'text': '''LINE1 +LINE2''', +}, +}.items(): + self.assertEqual(lineParser(inpt),otpt) + +unittest.main() -- cgit From 821e8a01fd33c3409e370b4d54cd90733e2503c0 Mon Sep 17 00:00:00 2001 From: Michael Manring Date: Mon, 11 Mar 2024 07:59:55 +1100 Subject: pwc259 solution in go --- challenge-259/pokgopun/go/ch-1.go | 34 +++++++++ challenge-259/pokgopun/go/ch-2.go | 154 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 challenge-259/pokgopun/go/ch-1.go create mode 100644 challenge-259/pokgopun/go/ch-2.go diff --git a/challenge-259/pokgopun/go/ch-1.go b/challenge-259/pokgopun/go/ch-1.go new file mode 100644 index 0000000000..ceec77ce84 --- /dev/null +++ b/challenge-259/pokgopun/go/ch-1.go @@ -0,0 +1,34 @@ +//# https://theweeklychallenge.org/blog/perl-weekly-challenge-259/ +/*# + +Task 1: Banking Day Offset + +Submitted by: [42]Lee Johnson + __________________________________________________________________ + + You are given a start date and offset counter. Optionally you also get + bank holiday date list. + + Given a number (of days) and a start date, return the number (of days) + adjusted to take into account non-banking days. In other words: convert + a banking day offset to a calendar day offset. + + Non-banking days are: +a) Weekends +b) Bank holidays + +Example 1 + +Input: $start_date = '2018-06-28', $offset = 3, $bank_holidays = ['2018-07-03'] +Output: '2018-07-04' + +Thursday bumped to Wednesday (3 day offset, with Monday a bank holiday) + +Example 2 + +Input: $start_date = '2018-06-28', $offset = 3 +Output: '2018-07-03' + +Task 2: Line Parser +#*/ +//# solution by pokgopun@gmail.com diff --git a/challenge-259/pokgopun/go/ch-2.go b/challenge-259/pokgopun/go/ch-2.go new file mode 100644 index 0000000000..186a72442b --- /dev/null +++ b/challenge-259/pokgopun/go/ch-2.go @@ -0,0 +1,154 @@ +//# https://theweeklychallenge.org/blog/perl-weekly-challenge-259/ +/*# + +Task 2: Line Parser + +Submitted by: [43]Gabor Szabo + __________________________________________________________________ + + You are given a line like below: +{% id field1="value1" field2="value2" field3=42 %} + + Where +a) "id" can be \w+. +b) There can be 0 or more field-value pairs. +c) The name of the fields are \w+. +b) The values are either number in which case we don't need parentheses or strin +g in + which case we need parentheses around them. + + The line parser should return structure like below: +{ + name => id, + fields => { + field1 => value1, + field2 => value2, + field3 => value3, + } +} + + It should be able to parse the following edge cases too: +{% youtube title="Title \"quoted\" done" %} + + and +{% youtube title="Title with escaped backslash \\" %} + + BONUS: Extend it to be able to handle multiline tags: +{% id filed1="value1" ... %} +LINES +{% endid %} + + You should expect the following structure from your line parser: +{ + name => id, + fields => { + field1 => value1, + field2 => value2, + field3 => value3, + } + text => LINES +} + __________________________________________________________________ + + Last date to submit the solution 23:59 (UK Time) Sunday 10th March + 2024. + __________________________________________________________________ + +SO WHAT DO YOU THINK ? +#*/ +//# solution by pokgopun@gmail.com + +package main + +import ( + "fmt" + "reflect" + "regexp" + "strconv" +) + +type kvpair map[string]string + +type parsed struct { + name, text string + fields kvpair +} + +type parser struct { + m []string + rgxLine, rgxKV *regexp.Regexp +} + +func newParser() parser { + return parser{ + rgxLine: regexp.MustCompile(`{%\s(?P\w+)(?P(?:\s\w+=(?:\d+|"(?:\\(?:"|\\)|[^"\\])+?"))+)?\s%}(?:\n(?P[\d\D]+?)\n\{%\sendid\s%})?`), + rgxKV: regexp.MustCompile(`\s(?P\w+)=(?P\d+|"(?:\\(?:"|\\)|[^"\\])+?")`), + } +} + +func (ps parser) parse(msg string) parsed { + ps.m = ps.rgxLine.FindStringSubmatch(msg) + p := parsed{name: ps.m[1], text: ps.m[3], fields: make(kvpair)} + if ps.m[2] != "" { + for _, kv := range ps.rgxKV.FindAllStringSubmatch(ps.m[2], -1) { + _, err := strconv.Atoi(kv[2]) + if err != nil { + kv[2], _ = strconv.Unquote(kv[2]) + } + p.fields[kv[1]] = kv[2] + } + } + return p +} + +func main() { + p := newParser() + for _, data := range []struct { + input string + output parsed + }{ + { + `{% youtube id=1234 title="Title \"quoted\" done" %}`, + parsed{ + name: "youtube", + fields: kvpair{ + "id": "1234", + "title": `Title "quoted" done`, + }, + }, + }, + { + `{% youtube title="Title with escaped backslash \\" id=4321 %}`, + parsed{ + name: "youtube", + fields: kvpair{ + "id": "4321", + "title": `Title with escaped backslash \`, + }, + }, + }, + { + `{% id %}`, + parsed{name: "id", fields: kvpair{}}, + }, + { + `{% youtube id=12345 title="mejoo and cats" cats="\"monji\" \\ \"bongji\" \\ \"hyuji\" \\ \"yoji\" \\ \"audrey\"" %} +soo +mejoo +{% endid %}`, + parsed{ + name: "youtube", + fields: kvpair{ + "id": "12345", + "cats": `"monji" \ "bongji" \ "hyuji" \ "yoji" \ "audrey"`, + "title": "mejoo and cats", + }, + text: `soo +mejoo`, + }, + }, + } { + //fmt.Println(p.parse(data.input)) + fmt.Println(reflect.DeepEqual(p.parse(data.input), data.output)) + } +} -- cgit From 0326b1d30f1ae291d80d865ae54e17e7c3e43479 Mon Sep 17 00:00:00 2001 From: Michael Manring Date: Tue, 12 Mar 2024 02:00:24 +1100 Subject: pwc259 solution in go --- challenge-259/pokgopun/go/ch-1.go | 90 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/challenge-259/pokgopun/go/ch-1.go b/challenge-259/pokgopun/go/ch-1.go index ceec77ce84..c013e96ffa 100644 --- a/challenge-259/pokgopun/go/ch-1.go +++ b/challenge-259/pokgopun/go/ch-1.go @@ -32,3 +32,93 @@ Output: '2018-07-03' Task 2: Line Parser #*/ //# solution by pokgopun@gmail.com + +package main + +import ( + "io" + "log" + "os" + "slices" + "time" + + "github.com/google/go-cmp/cmp" +) + +const datePttrn = "2006-01-02" + +// logic is similar to python version +func bankingDayOffset(startDate string, offset uint, bankHolidays []string) string { + dstart, err := time.Parse(datePttrn, startDate) + if err != nil { + log.Fatal("invalid date string") + } + switch dstart.Weekday() { // skip back to Friday if start at weekend + case time.Saturday: + dstart = dstart.AddDate(0, 0, -1) + case time.Sunday: + dstart = dstart.AddDate(0, 0, -2) + } + days := 7*(int(offset)/5) + int(offset)%5 // convert workday offset to everyday offset => 7 days * weekCount (i.e. int(offset)/5) + partial week offset + if int(dstart.Weekday())+int(offset)%5 > 5 { // skip weekend if partial week offset int(offset)%5 move dstart beyond current weekday + days += 2 + } + dend := dstart.AddDate(0, 0, days) + for _, hol := range newHolidays(bankHolidays) { + if dstart.Before(hol) && !dend.Before(hol) { // move forward with holidays one by one + dend = dend.AddDate(0, 0, 1) + if dend.Weekday() > time.Friday { // skip to next monday if such move hit Saturday + dend = dend.AddDate(0, 0, 2) + } + } + } + return dend.Format(datePttrn) +} + +type holidays []time.Time + +// newHolidays silently filter out invalid and duplicated date strings and weekend, dates will be sorted ascendingly as well +func newHolidays(dateStrs []string) holidays { + var hols holidays + m := make(map[time.Time]struct{}) + slices.Sort(dateStrs) + for _, dateStr := range dateStrs { + date, err := time.Parse(datePttrn, dateStr) + if err == nil { + switch date.Weekday() { + case time.Saturday, time.Sunday: + continue + } + _, ok := m[date] + if !ok { + m[date] = struct{}{} + hols = append(hols, date) + } + } + } + return hols +} + +func main() { + for _, data := range []struct { + output, start string + offset uint + holidays []string + }{ + {"2018-07-04", "2018-06-28", 3, []string{"2018-07-03"}}, + {"2018-07-03", "2018-06-28", 3, []string{}}, + {"2018-07-05", "2018-06-28", 3, []string{"2018-07-02", "2018-07-03"}}, + {"2018-07-05", "2018-06-28", 3, []string{"2018-07-06", "2018-07-03", "2018-07-02"}}, + {"2018-07-06", "2018-06-28", 3, []string{"2018-07-02", "2018-07-03", "2018-07-05"}}, + {"2018-07-06", "2018-06-28", 3, []string{"2018-07-02", "2018-07-03", "2018-07-05", "2024-03-05"}}, + {"2018-07-06", "2018-06-28", 3, []string{"2018-07-02", "2018-07-03", "2018-07-05", "1979-07-09"}}, + {"2018-07-13", "2018-06-28", 8, []string{"2018-07-02", "2018-07-03", "2018-07-05", "1979-07-09"}}, + {"2018-07-16", "2018-06-28", 9, []string{"2018-07-02", "2018-07-03", "2018-07-05", "1979-07-09"}}, + {"2018-07-23", "2018-06-28", 14, []string{"2018-07-02", "2018-07-03", "2018-07-05", "1979-07-09"}}, + {"2018-07-25", "2018-06-28", 14, []string{"2018-07-02", "2018-07-03", "2018-07-05", "2018-07-11", "2018-07-18"}}, + {"2018-07-05", "2018-06-29", 3, []string{"2018-07-03"}}, + {"2018-07-05", "2018-06-30", 3, []string{"2018-07-03"}}, + } { + io.WriteString(os.Stdout, cmp.Diff(bankingDayOffset(data.start, data.offset, data.holidays), data.output)) // blank if ok, otherwise show the differences + } +} -- cgit From 379206ccf0a24111b37b9c6996dc21fe576a3e6b Mon Sep 17 00:00:00 2001 From: David Ferrone Date: Mon, 11 Mar 2024 18:17:44 -0400 Subject: 5 Years of PWC! --- challenge-260/zapwai/c/ch-1.c | 84 +++++++++++++++++++++++++++++++++ challenge-260/zapwai/c/ch-2.c | 81 +++++++++++++++++++++++++++++++ challenge-260/zapwai/javascript/ch-1.js | 21 +++++++++ challenge-260/zapwai/javascript/ch-2.js | 40 ++++++++++++++++ challenge-260/zapwai/perl/ch-1.pl | 25 ++++++++++ challenge-260/zapwai/perl/ch-2.pl | 43 +++++++++++++++++ challenge-260/zapwai/python/ch-1.py | 27 +++++++++++ challenge-260/zapwai/python/ch-2.py | 34 +++++++++++++ challenge-260/zapwai/rust/ch-1.rs | 30 ++++++++++++ challenge-260/zapwai/rust/ch-2.rs | 51 ++++++++++++++++++++ 10 files changed, 436 insertions(+) create mode 100644 challenge-260/zapwai/c/ch-1.c create mode 100644 challenge-260/zapwai/c/ch-2.c create mode 100644 challenge-260/zapwai/javascript/ch-1.js create mode 100644 challenge-260/zapwai/javascript/ch-2.js create mode 100644 challenge-260/zapwai/perl/ch-1.pl create mode 100644 challenge-260/zapwai/perl/ch-2.pl create mode 100644 challenge-260/zapwai/python/ch-1.py create mode 100644 challenge-260/zapwai/python/ch-2.py create mode 100644 challenge-260/zapwai/rust/ch-1.rs create mode 100644 challenge-260/zapwai/rust/ch-2.rs diff --git a/challenge-260/zapwai/c/ch-1.c b/challenge-260/zapwai/c/ch-1.c new file mode 100644 index 0000000000..ec3b7577b9 --- /dev/null +++ b/challenge-260/zapwai/c/ch-1.c @@ -0,0 +1,84 @@ +#include +#include +#define MAX 100 +#define BORK -111111 /* unusable key/value */ + +struct hash { + int key[MAX]; + int val[MAX]; + int length; +}; + +void init(struct hash *h) { + for (int i = 0; i < MAX; i++) { + h->key[i] = BORK; + h->val[i] = BORK; + } + h->length = 0; +} + +int get(struct hash h, int key) { + for (int i = 0; i < MAX; i++) + if (h.key[i] == key) + return h.val[i]; + return BORK; +} + +void set(struct hash *h, int key, int value) { + for (int i = 0; i < MAX; i++) + if (h->key[i] == key) + h->val[i] = value; +} + +void insert(struct hash *h, int key, int value) { + int index = h->length; + h->key[index] = key; + h->val[index] = value; + h->length++; +} + +bool contains(struct hash h, int key) { + for (int i = 0; i < MAX; i++) + if (h.key[i] == key) + return true; + return false; +} + +int has_uniq_freq(struct hash h) { + for (int i = 1; i < h.length; i++) + for (int j = 0; j < i; j++) + if (h.val[j] == h.val[i]) + return 0; + return 1; +} + +void proc(int len, int l[]) { + printf("Input: { "); + for (int i = 0; i < len; i++) + printf("%d ", l[i]); + printf("}\n"); + + struct hash f; + init(&f); + + for (int i = 0; i < len; i++) + if (contains(f, l[i])) + set(&f, l[i], get(f,l[i]) + 1); + else + insert(&f, l[i], 1); + + printf("Output %d\n", has_uniq_freq(f)); +} + +int main() { + int l1[] = {1,2,2,1,1,3}; + int l2[] = {1,2,3}; + int l3[] = {-2,0,1,-2,1,1,0,1,-2,9}; + int s1 = sizeof(l1) / sizeof(int); + int s2 = sizeof(l2) / sizeof(int); + int s3 = sizeof(l3) / sizeof(int); + proc(s1, l1); + proc(s2, l2); + proc(s3, l3); +} + diff --git a/challenge-260/zapwai/c/ch-2.c b/challenge-260/zapwai/c/ch-2.c new file mode 100644 index 0000000000..a499718f35 --- /dev/null +++ b/challenge-260/zapwai/c/ch-2.c @@ -0,0 +1,81 @@ +#include +#include +#include +#define MAX_WORD_LEN 50 + +void sortme(char** words, int wordlen) { + int cnt; + do { + cnt = 0; + for (int i = 0; i < wordlen - 1; i++) + if (strcmp(words[i+1], words[i]) < 0) { + char* tmp = words[i+1]; + words[i+1] = words[i]; + words[i] = tmp; + cnt++; + } + } while (cnt > 0); +} + +void insert_uniquely(char* word, int wordlen, char** h, int* hlen) { + for (int i = 0; i < *hlen; i++) + if (0 == strcmp(h[i], word)) + return; + h[*hlen] = malloc(MAX_WORD_LEN * sizeof(char)); + strncpy(h[*hlen], word, wordlen); + ++*hlen; +} + +int seek_word(char* word, char** sorted, int sortlen) { + for (int i = 0; i < sortlen; i++) + if (0 == strcmp(sorted[i], word)) + return i; + return -1; +} + +void swap(int i, int j, char list[]) { + char tmp = list[i]; + list[i] = list[j]; + list[j] = tmp; +} + +void L(int k, char list[], char** h, int *hlen, int wordlength) { + if (k == 1) + insert_uniquely(list, wordlength, h, hlen); + else { + L(k - 1, list, h, hlen, wordlength); + for (int i = 0; i <= k - 2; i++) { + if (k % 2 == 0) + swap(i, k-1, list); + else + swap(0, k-1, list); + L(k - 1, list, h, hlen, wordlength); + } + } +} + +void proc(char* word) { + printf("Input: %s\n", word); + char** h = malloc(1000 * sizeof(char*)); + int hlen = 0; + + char list[strlen(word)]; + for (int i = 0; i < strlen(word); i++) + list[i] = word[i]; + + L(strlen(word), list, h, &hlen, strlen(word)); + + sortme(h, hlen); + + int ind = seek_word(word, h, hlen); + printf("Output: %d\n", 1 + ind); + for (int i = 0; i < hlen; i++) + free(h[i]); + free(h); +} + +int main() { + proc("CAT"); + proc("GOGGLE"); + proc("SECRET"); +} diff --git a/challenge-260/zapwai/javascript/ch-1.js b/challenge-260/zapwai/javascript/ch-1.js new file mode 100644 index 0000000000..3e4fbc4b42 --- /dev/null +++ b/challenge-260/zapwai/javascript/ch-1.js @@ -0,0 +1,21 @@ +let l1 = [1,2,2,1,1,3]; +let l2 = [1,2,3]; +let l3 = [-2,0,1,-2,1,1,0,1,-2,9]; +for (let l of [l1, l2, l3]) + proc(l); + +function proc(l) { + console.log("Input:", l); + let f = {}; + for (let i of l) + (i in f) ? f[i]++ : f[i] = 1; + let freq = []; + let output = 1; + for (let v of Object.values(f)) { + if (freq.includes(v)) + output = 0; + else + freq.push(v); + } + console.log("Output:", output); +} diff --git a/challenge-260/zapwai/javascript/ch-2.js b/challenge-260/zapwai/javascript/ch-2.js new file mode 100644 index 0000000000..c7078f49fa --- /dev/null +++ b/challenge-260/zapwai/javascript/ch-2.js @@ -0,0 +1,40 @@ +function proc(word) { + console.log("Input:", word); + let h = {}; + L(word.length, word.split(''), h); + let sorted = Object.keys(h).sort(); + console.log("Output:", 1 + seek_word(word, sorted)); +} + +function L(k, list, h) { + if (k == 1) + h[list.join('')] = 1; + else { + L(k-1, list, h); + for (let i = 0; i < k-1; i++) { + if (k % 2 == 0) + swap(i, k-1, list); + else + swap(0, k-1, list); + L(k-1, list, h); + } + } +} + +function swap(i, j, list) { + let tmp = list[i]; + list[i] = list[j]; + list[j] = tmp; +} + +function seek_word(word, sorted) { + for (let i = 0; i < sorted.length; i++) + if (sorted[i] == word) + return i; + + return -1; +} + +proc("CAT"); +proc("GOGGLE"); +proc("SECRET"); diff --git a/challenge-260/zapwai/perl/ch-1.pl b/challenge-260/zapwai/perl/ch-1.pl new file mode 100644 index 0000000000..b4c19a9415 --- /dev/null +++ b/challenge-260/zapwai/perl/ch-1.pl @@ -0,0 +1,25 @@ +use v5.36; +my @ints = (1,2,2,1,1,3); +proc(@ints); +my @ints2 = (1,2,3); +proc(@ints2); +my @ints3 = (-2,0,1,-2,1,1,0,1,-2,9); +proc(@ints3); + +sub proc(@ints) { + say "Input: \@ints = (", join(", ", @ints).")"; + say "Output: ", has_uniq_freq(@ints); +} + +sub has_uniq_freq(@ints) { + my %f = map { $_, 0 } @ints; + $f{$_}++ foreach (@ints); + my %g = map { $_, 0 } (values %f); + $g{$_}++ foreach (values %f); + for ( values %g ) { + if ($_ > 1) { + return 0; + } + } + return 1; +} diff --git a/challenge-260/zapwai/perl/ch-2.pl b/challenge-260/zapwai/perl/ch-2.pl new file mode 100644 index 0000000000..d186c35bc3 --- /dev/null +++ b/challenge-260/zapwai/perl/ch-2.pl @@ -0,0 +1,43 @@ +use v5.36; + +sub proc($word) { + my %words; + say "Input: $word"; + my @let = split "", $word; + L(length $word, \@let, \%words); + my @sorted = sort keys %words; + say "Output: ", 1 + seek_word($word, @sorted); +} + +sub L($k, $list, $r) { + if ($k == 1) { + $$r{join("",@$list)} = 1; + } else { + L($k-1, $list, $r); + for my $i (0 .. $k-2) { + if ($k % 2 == 0) { + swap($i, $k-1, $list); + } else { + swap(0, $k-1, $list); + } + L($k-1, $list, $r); + } + } +} + +sub swap($i, $j, $list) { + my $hold = $$list[$i]; + $$list[$i] = $$list[$j]; + $$list[$j] = $hold; +} + +sub seek_word ($word, @sorted) { + for my $i (0 .. $#sorted) { + return $i if ($sorted[$i] eq $word); + } + return -1; +} + +proc("CAT"); +proc("GOOGLE"); +proc("SECRET"); diff --git a/challenge-260/zapwai/python/ch-1.py b/challenge-260/zapwai/python/ch-1.py new file mode 100644 index 0000000000..4de8664aea --- /dev/null +++ b/challenge-260/zapwai/python/ch-1.py @@ -0,0 +1,27 @@ +def has_uniq_freq(l): + freq = {} + for item in l: + if item in freq.keys(): + freq[item] += 1 + else: + freq[item] = 1 + gq = {} + for v in freq.values(): + if v in gq.keys(): + gq[v] += 1 + else: + gq[v] = 0 + for v in gq.values(): + if v > 1: + return 0 + return 1 + +def proc(l): + print("Input:", l); + print("Output:", has_uniq_freq(l)) + +l1 = [1,2,2,1,1,3] +l2 = [1,2,3] +l3 = [-2,0,1,-2,1,1,0,1,-2,9] +for l in [l1, l2, l3]: + proc(l) diff --git a/challenge-260/zapwai/python/ch-2.py b/challenge-260/zapwai/python/ch-2.py new file mode 100644 index 0000000000..bdfe08eca0 --- /dev/null +++ b/challenge-260/zapwai/python/ch-2.py @@ -0,0 +1,34 @@ +def seek_word(word, sorts): + for i in range(len(sorts)): + if sorts[i] == word: + return i + return -1 + +def L(k, mylist, h): + if k == 1: + h[''.join(mylist)] = 1 + else: + L(k-1, mylist, h) + for i in range(k-1): + if k % 2 == 0: + swap(i, k-1, mylist) + else: + swap(0, k-1, mylist) + L(k-1, mylist, h) + +def swap(i, j, mylist): + tmp = mylist[i] + mylist[i] = mylist[j] + mylist[j] = tmp + +def proc(word): + perms = {} + print("Input:", word) + let = list(word) + L(len(word), let, perms) + sorts = sorted(perms.keys()) + print("Output", 1 + seek_word(word, sorts)) + +proc("CAT") +proc("GOGGLE") +proc("SECRET") diff --git a/challenge-260/zapwai/rust/ch-1.rs b/challenge-260/zapwai/rust/ch-1.rs new file mode 100644 index 0000000000..7e0cf5afe2 --- /dev/null +++ b/challenge-260/zapwai/rust/ch-1.rs @@ -0,0 +1,30 @@ +use std::collections::HashMap; + +fn main() { + let l1 = [1,2,2,1,1,3]; + let l2 = [1,2,3]; + let l3 = [-2,0,1,-2,1,1,0,1,-2,9]; + let lists : Vec<&[i32]> = vec![&l1, &l2, &l3]; + for l in lists { + proc(&l); + } +} + +fn proc(l : &[i32]) { + println!("Input: {:?}", l); + let mut f = HashMap::new(); + for k in l { + let entry = f.entry(k).or_insert(0); + *entry += 1; + } + let mut freqs = vec![]; + let mut out = 1; + for v in f.values() { + if freqs.contains(v) { + out = 0; + } else { + freqs.push(*v); + } + } + println!("Output: {out}"); +} diff --git a/challenge-260/zapwai/rust/ch-2.rs b/challenge-260/zapwai/rust/ch-2.rs new file mode 100644 index 0000000000..62322619c3 --- /dev/null +++ b/challenge-260/zapwai/rust/ch-2.rs @@ -0,0 +1,51 @@ +use std::collections::HashMap; + +fn proc(word : &str) { + let mut h = HashMap::new(); + println!("Input: {}", word); + let mut letters = word.chars().collect::>(); + l(word.len(), &mut letters, &mut h); + let mut sorted :Vec = Vec::new(); + for k in h.keys() { + sorted.push(k.to_string()); + } + sorted.sort(); + println!("Output {}", 1 + seek_word(word, sorted)); +} + +fn l(k :usize, list : &mut Vec, h : &mut HashMap) { + if k == 1 { + h.insert(list.iter().collect(), 1); + } else { + l(k - 1, list, h); + for i in 0 ..= k - 2 { + if k % 2 == 0 { + swap(i, k-1, list); + } else { + swap(0, k-1, list); + } + l(k-1, list, h); + } + } +} + +fn swap(i :usize, j :usize, list :&mut Vec) { + let tmp = list[i]; + list[i] = list[j]; + list[j] = tmp; +} + +fn seek_word(word :&str, sorted : Vec) -> usize{ + for i in 0 .. sorted.len() { + if sorted[i] == word.to_string(){ + return i; + } + } + return 10000; +} + +fn main() { + proc("CAT"); + proc("GOGGLE"); + proc("SECRET"); +} -- cgit From 87dfd7b9a9b717fa6847ee0e0710e2798ea76ce6 Mon Sep 17 00:00:00 2001 From: Michael Manring Date: Tue, 12 Mar 2024 11:22:11 +1100 Subject: pwc260 solution in python --- challenge-260/pokgopun/python/ch-1.py | 56 +++++++++++++++++++++++++++++ challenge-260/pokgopun/python/ch-2.py | 68 +++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 challenge-260/pokgopun/python/ch-1.py create mode 100644 challenge-260/pokgopun/python/ch-2.py diff --git a/challenge-260/pokgopun/python/ch-1.py b/challenge-260/pokgopun/python/ch-1.py new file mode 100644 index 0000000000..734382ae7c --- /dev/null +++ b/challenge-260/pokgopun/python/ch-1.py @@ -0,0 +1,56 @@ +### https://theweeklychallenge.org/blog/perl-weekly-challenge-260/ +""" + +Task 1: Unique Occurrences + +Submitted by: [42]Mohammad Sajid Anwar + __________________________________________________________________ + + You are given an array of integers, @ints. + + Write a script to return 1 if the number of occurrences of each value + in the given array is unique or 0 otherwise. + +Example 1 + +Input: @ints = (1,2,2,1,1,3) +Output: 1 + +The number 1 occurred 3 times. +The number 2 occurred 2 times. +The number 3 occurred 1 time. + +All occurrences are unique, therefore the output is 1. + +Example 2 + +Input: @ints = (1,2,3) +Output: 0 + +Example 3 + +Input: @ints = (-2,0,1,-2,1,1,0,1,-2,9) +Output: 1 + +Task 2: Dictionary Rank +""" +### solution by pokgopun@gmail.com + +def UO(tup: tuple): + s = set(tup) + return len(s)==len(set(tup.count(e) for e in s)) + +import unittest + +class TestUO(unittest.TestCase): + def test(self): + for inpt, otpt in { + (1,2,2,1,1,3): 1, + (1,2,3): 0, + (-2,0,1,-2,1,1,0,1,-2,9): 1, + }.items(): + self.assertEqual(UO(inpt),otpt) + +unittest.main() + + diff --git a/challenge-260/pokgopun/python/ch-2.py b/challenge-260/pokgopun/python/ch-2.py new file mode 100644 index 0000000000..6925831197 --- /dev/null +++ b/challenge-260/pokgopun/python/ch-2.py @@ -0,0 +1,68 @@ +### https://theweeklychallenge.org/blog/perl-weekly-challenge-260/ +""" + +Task 2: Dictionary Rank + +Submitted by: [43]Mark Anderson + __________________________________________________________________ + + You are given a word, $word. + + Write a script to compute the dictionary rank of the given word. + +Example 1 + +Input: $word = 'CAT' +Output: 3 + +All possible combinations of the letters: +CAT, CTA, ATC, TCA, ACT, TAC + +Arrange them in alphabetical order: +ACT, ATC, CAT, CTA, TAC, TCA + +CAT is the 3rd in the list. +Therefore the dictionary rank of CAT is 3. + +Example 2 + +Input: $word = 'GOOGLE' +Output: 88 + +Example 3 + +Input: $word = 'SECRET' +Output: 255 + __________________________________________________________________ + + Last date to submit the solution 23:59 (UK Time) Sunday 17th March + 2024. + __________________________________________________________________ + +SO WHAT DO YOU THINK ? +""" +### solution by pokgopun@gmail.com + +from itertools import permutations + +def DC(word: str): + return tuple( + sorted( + set( + permutations(word,len(word)) + ) + ) + ).index(tuple(word)) + 1 + +import unittest + +class TestDC(unittest.TestCase): + def test(self): + for inpt, otpt in { + 'CAT': 3, + 'GOOGLE': 88, + 'SECRET': 255, + }.items(): + self.assertEqual(DC(inpt),otpt) + +unittest.main() -- cgit From 867127a74fe3c558a20cba4b1cd609f8e987e4ba Mon Sep 17 00:00:00 2001 From: Michael Manring Date: Tue, 12 Mar 2024 13:50:16 +1100 Subject: pwc260 solution in go --- challenge-260/pokgopun/go/ch-1.go | 104 ++++++++++++++++++++++++++++++++++++++ challenge-260/pokgopun/go/ch-2.go | 98 +++++++++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 challenge-260/pokgopun/go/ch-1.go create mode 100644 challenge-260/pokgopun/go/ch-2.go diff --git a/challenge-260/pokgopun/go/ch-1.go b/challenge-260/pokgopun/go/ch-1.go new file mode 100644 index 0000000000..a401e1588a --- /dev/null +++ b/challenge-260/pokgopun/go/ch-1.go @@ -0,0 +1,104 @@ +//# https://theweeklychallenge.org/blog/perl-weekly-challenge-260/ +/*# + +Task 1: Unique Occurrences + +Submitted by: [42]Mohammad Sajid Anwar + __________________________________________________________________ + + You are given an array of integers, @ints. + + Write a script to return 1 if the number of occurrences of each value + in the given array is unique or 0 otherwise. + +Example 1 + +Input: @ints = (1,2,2,1,1,3) +Output: 1 + +The number 1 occurred 3 times. +The number 2 occurred 2 times. +The number 3 occurred 1 time. + +All occurrences are unique, therefore the output is 1. + +Example 2 + +Input: @ints = (1,2,3) +Output: 0 + +Example 3 + +Input: @ints = (-2,0,1,-2,1,1,0,1,-2,9) +Output: 1 + +Task 2: Dictionary Rank +#*/ +//# solution by pokgopun@gmail.com + +package main + +import ( + "io" + "os" + + "github.com/google/go-cmp/cmp" +) + +type ints []int + +type myMap map[int]int + +func newMyMap() myMap { + return make(myMap) +} + +func (mm myMap) proc(is ints) { + clear(mm) + for _, v := range is { + mm[v]++ + } +} + +func (mm myMap) keys() ints { + var s ints + for k := range mm { + s = append(s, k) + } + return s +} + +func (mm myMap) values() ints { + var s ints + for _, v := range mm { + s = append(s, v) + } + return s +} + +func (mm myMap) uo(is ints) bool { + mm.proc(is) + //fmt.Println("mm = ", mm) + count_uniq_elem := len(mm.keys()) + //fmt.Println("count_uniq_elem =", count_uniq_elem) + mm.proc(mm.values()) + //fmt.Println("mm = ", mm) + count_uniq_occur := len(mm.keys()) + //fmt.Println("count_uniq_occur =", count_uniq_occur) + return count_uniq_elem == count_uniq_occur +} + +func main() { + mm := newMyMap() + for _, data := range []struct { + input ints + output bool + }{ + {ints{1, 2, 2, 1, 1, 3}, true}, + {ints{1, 2, 3}, false}, + {ints{-2, 0, 1, -2, 1, 1, 0, 1, -2, 9}, true}, + } { + //fmt.Println(data.input) + io.WriteString(os.Stdout, cmp.Diff(mm.uo(data.input), data.output)) // blank if ok, otherwise show the differences + } +} diff --git a/challenge-260/pokgopun/go/ch-2.go b/challenge-260/pokgopun/go/ch-2.go new file mode 100644 index 0000000000..aba232c3e9 --- /dev/null +++ b/challenge-260/pokgopun/go/ch-2.go @@ -0,0 +1,98 @@ +//# https://theweeklychallenge.org/blog/perl-weekly-challenge-260/ +/*# + +Task 2: Dictionary Rank + +Submitted by: [43]Mark Anderson + __________________________________________________________________ + + You are given a word, $word. + + Write a script to compute the dictionary rank of the given word. + +Example 1 + +Input: $word = 'CAT' +Output: 3 + +All possible combinations of the letters: +CAT, CTA, ATC, TCA, ACT, TAC + +Arrange them in alphabetical order: +ACT, ATC, CAT, CTA, TAC, TCA + +CAT is the 3rd in the list. +Therefore the dictionary rank of CAT is 3. + +Example 2 + +Input: $word = 'GOOGLE' +Output: 88 + +Example 3 + +Input: $word = 'SECRET' +Output: 255 + __________________________________________________________________ + + Last date to submit the solution 23:59 (UK Time) Sunday 17th March + 2024. + __________________________________________________________________ + +SO WHAT DO YOU THINK ? +#*/ +//# solution by pokgopun@gmail.com + +package main + +import ( + "io" + "os" + "slices" + "strings" + + "github.com/google/go-cmp/cmp" +) + +func dc(word string) int { + var res string + s := strings.Split(permute(word, "", &res), " ") + slices.Sort(s) + l := len(s) + i, j := 0, l + for j > 1 { + if s[i] == s[i+1] { + copy(s[i:], s[i+1:]) + l-- + } else { + i++ + } + j-- + } + return slices.Index(s, word) + 1 +} + +func permute(s, t string, res *string) string { + if len(s) > 0 { + for i, v := range []byte(s) { + permute(s[:i]+s[i+1:], t+string(v), res) + } + } else { + *res += " " + t + return "" + } + return (*res)[1:] +} + +func main() { + for _, data := range []struct { + input string + output int + }{ + {"CAT", 3}, + {"GOOGLE", 88}, + {"SECRET", 255}, + } { + io.WriteString(os.Stdout, cmp.Diff(dc(data.input), data.output)) // blank if ok, otherwise show the differences + } +} -- cgit From ce6d2a4181a05281b6a9f56de4830505a1505c4d Mon Sep 17 00:00:00 2001 From: Roger Bell_West Date: Tue, 12 Mar 2024 09:28:03 +0000 Subject: RogerBW solutions for challenge no. 260 --- challenge-260/roger-bell-west/javascript/ch-1.js | 38 +++ challenge-260/roger-bell-west/javascript/ch-2.js | 68 ++++++ challenge-260/roger-bell-west/kotlin/ch-1.kt | 34 +++ challenge-260/roger-bell-west/kotlin/ch-2.kt | 77 ++++++ challenge-260/roger-bell-west/lua/ch-1.lua | 42 ++++ challenge-260/roger-bell-west/lua/ch-2.lua | 102 ++++++++ challenge-260/roger-bell-west/perl/ch-1.pl | 22 ++ challenge-260/roger-bell-west/perl/ch-2.pl | 29 +++ challenge-260/roger-bell-west/postscript/ch-1.ps | 91 +++++++ challenge-260/roger-bell-west/postscript/ch-2.ps | 290 +++++++++++++++++++++++ challenge-260/roger-bell-west/python/ch-1.py | 27 +++ challenge-260/roger-bell-west/python/ch-2.py | 29 +++ challenge-260/roger-bell-west/raku/ch-1.p6 | 19 ++ challenge-260/roger-bell-west/raku/ch-2.p6 | 24 ++ challenge-260/roger-bell-west/ruby/ch-1.rb | 33 +++ challenge-260/roger-bell-west/ruby/ch-2.rb | 36 +++ challenge-260/roger-bell-west/rust/ch-1.rs | 26 ++ challenge-260/roger-bell-west/rust/ch-2.rs | 33 +++ challenge-260/roger-bell-west/scala/ch-1.scala | 36 +++ challenge-260/roger-bell-west/scala/ch-2.scala | 76 ++++++ challenge-260/roger-bell-west/tests.yaml | 36 +++ 21 files changed, 1168 insertions(+) create mode 100755 challenge-260/roger-bell-west/javascript/ch-1.js create mode 100755 challenge-260/roger-bell-west/javascript/ch-2.js create mode 100644 challenge-260/roger-bell-west/kotlin/ch-1.kt create mode 100644 challenge-260/roger-bell-west/kotlin/ch-2.kt create mode 100755 challenge-260/roger-bell-west/lua/ch-1.lua create mode 100755 challenge-260/roger-bell-west/lua/ch-2.lua create mode 100755 challenge-260/roger-bell-west/perl/ch-1.pl create mode 100755 challenge-260/roger-bell-west/perl/ch-2.pl create mode 100644 challenge-260/roger-bell-west/postscript/ch-1.ps create mode 100644 challenge-260/roger-bell-west/postscript/ch-2.ps create mode 100755 challenge-260/roger-bell-west/python/ch-1.py create mode 100755 challenge-260/roger-bell-west/python/ch-2.py create mode 100755 challenge-260/roger-bell-west/raku/ch-1.p6 create mode 100755 challenge-260/roger-bell-west/raku/ch-2.p6 create mode 100755 challenge-260/roger-bell-west/ruby/ch-1.rb create mode 100755 challenge-260/roger-bell-west/ruby/ch-2.rb create mode 100755 challenge-260/roger-bell-west/rust/ch-1.rs create mode 100755 challenge-260/roger-bell-west/rust/ch-2.rs create mode 100644 challenge-260/roger-bell-west/scala/ch-1.scala create mode 100644 challenge-260/roger-bell-west/scala/ch-2.scala create mode 100644 challenge-260/roger-bell-west/tests.yaml diff --git a/challenge-260/roger-bell-west/javascript/ch-1.js b/challenge-260/roger-bell-west/javascript/ch-1.js new file mode 100755 index 0000000000..f662f3c60d --- /dev/null +++ b/challenge-260/roger-bell-west/javascript/ch-1.js @@ -0,0 +1,38 @@ +#! /usr/bin/node + +"use strict" + +function uniqueoccurrences(a) { + let c = new Map; + for (let n of a) { + if (c.has(n)) { + c.set(n, c.get(n) + 1); + } else { + c.set(n, 1); + } + } + if (c.size == new Set(c.values()).size) { + return 1; + } else { + return 0; + } +} + +if (uniqueoccurrences([1, 2, 2, 1, 1, 3]) == 1) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); +if (uniqueoccurrences([1, 2, 3]) == 0) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); +if (uniqueoccurrences([-2, 0, 1, -2, 1, 1, 0, 1, -2, 9]) == 1) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write("\n"); diff --git a/challenge-260/roger-bell-west/javascript/ch-2.js b/challenge-260/roger-bell-west/javascript/ch-2.js new file mode 100755 index 0000000000..0c7fc40efd --- /dev/null +++ b/challenge-260/roger-bell-west/javascript/ch-2.js @@ -0,0 +1,68 @@ +#! /usr/bin/node + +"use strict" + +function permute(a) { + let out = []; + let n=a.length; + let c=[]; + for (let i = 0; i < n; i++) { + c.push(0); + } + out.push([...a]); + let i=0; + while (true) { + if (i >= n) { + break; + } + if (c[i] < i) { + if (i % 2 == 0) { + [a[0],a[i]] = [a[i],a[0]]; + } else { + [a[c[i]],a[i]] = [a[i],a[c[i]]]; + } + out.push([...a]); + c[i]++; + i=0; + } else { + c[i]=0; + i++; + } + } + return out; +} + +function dictionaryrank(a) { + const c = a.split(""); + let d = new Set; + for (let o of permute(c)) { + d.add(o.join("")); + } + let dd = new Array(...d); + dd.sort(); + for (let i = 0; i < dd.length; i++) { + if (dd[i] == a) { + return i + 1; + } + } + return 0; +} + +if (dictionaryrank('CAT') == 3) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); +if (dictionaryrank('GOOGLE') == 88) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); +if (dictionaryrank('SECRET') == 255) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write("\n"); diff --git a/challenge-260/roger-bell-west/kotlin/ch-1.kt b/challenge-260/roger-bell-west/kotlin/ch-1.kt new file mode 100644 index 0000000000..844714ccce --- /dev/null +++ b/challenge-260/roger-bell-west/kotlin/ch-1.kt @@ -0,0 +1,34 @@ +fun uniqueoccurrences(a: List): Int { + var c = mutableMapOf().withDefault({0}) + for (n in a) { + c.set(n, c.getValue(n) + 1) + } + if (c.size == c.values.toSet().size) { + return 1 + } else { + return 0 + } +} + +fun main() { + + if (uniqueoccurrences(listOf(1, 2, 2, 1, 1, 3)) == 1) { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (uniqueoccurrences(listOf(1, 2, 3)) == 0) { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (uniqueoccurrences(listOf(-2, 0, 1, -2, 1, 1, 0, 1, -2, 9)) == 1) { + print("Pass") + } else { + print("Fail") + } + println("") + +} diff --git a/challenge-260/roger-bell-west/kotlin/ch-2.kt b/challenge-260/roger-bell-west/kotlin/ch-2.kt new file mode 100644 index 0000000000..c437a9e4fd --- /dev/null +++ b/challenge-260/roger-bell-west/kotlin/ch-2.kt @@ -0,0 +1,77 @@ +fun permute(aa: List): ArrayList> { + var a = ArrayList() + for (i in aa) { + a.add(i) + } + var out = ArrayList>() + val n = a.size + var c = ArrayList(); + for (i in 0..n-1) { + c.add(0) + } + out.add(a.toList()) + var i = 0 + while (true) { + if (i >= n) { + break + } + if (c[i] < i) { + if (i % 2 == 0) { + val tmp = a[0] + a[0] = a[i] + a[i] = tmp + } else { + val tmp = a[c[i]] + a[c[i]] = a[i] + a[i] = tmp + } + out.add(a.toList()) + c[i] += 1 + i = 0 + } else { + c[i] = 0 + i += 1 + } + } + return out +} + +fun dictionaryrank(a: String): Int { + val c = a.toCharArray().toList() + var d = mutableSetOf() + for (o in permute(c)) { + d.add(o.joinToString("")) + } + var dd = ArrayList(d) + dd.sort() + var r = 0 + dd.forEachIndexed{i, s -> + if (s == a) { + r = i + 1 + } + } + return r +} + +fun main() { + + if (dictionaryrank("CAT") == 3) { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (dictionaryrank("GOOGLE") == 88) { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (dictionaryrank("SECRET") == 255) { + print("Pass") + } else { + print("Fail") + } + println("") + +} diff --git a/challenge-260/roger-bell-west/lua/ch-1.lua b/challenge-260/roger-bell-west/lua/ch-1.lua new file mode 100755 index 0000000000..2cdfb441b3 --- /dev/null +++ b/challenge-260/roger-bell-west/lua/ch-1.lua @@ -0,0 +1,42 @@ +#! /usr/bin/lua + +function uniqueoccurrences(a) + local c = {} + for _, n in ipairs(a) do + if c[n] == nil then + c[n] = 1 + else + c[n] = c[n] + 1 + end + end + local s = {} + for _, v in pairs(c) do + if s[v] ~= nil then + return 0 + end + s[v] = true + end + return 1 +end + +if uniqueoccurrences({1, 2, 2, 1, 1, 3}) == 1 then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if uniqueoccurrences({1, 2, 3}) == 0 then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if uniqueoccurrences({-2, 0, 1, -2, 1, 1, 0, 1, -2, 9}) == 1 then + io.write("Pass") +else + io.write("FAIL") +end +print("") + diff --git a/challenge-260/roger-bell-west/lua/ch-2.lua b/challenge-260/roger-bell-west/lua/ch-2.lua new file mode 100755 index 0000000000..d9407cf3ad --- /dev/null +++ b/challenge-260/roger-bell-west/lua/ch-2.lua @@ -0,0 +1,102 @@ +#! /usr/bin/lua + +function deepcopy(src) + local dst = {} + for k, v in pairs(src) do + if type(v) == "table" then + v = deepcopy(v) + end + dst[k] = v + end + return dst +end + +function permute(a) + local out = {} + local n = #a + local c = {} + for i = 1,n do + table.insert(c, 1) + end + table.insert(out, deepcopy(a)) + local i=1 + while true do + if i > n then + break + end + if c[i] < i then + if i % 2 == 1 then + a[1],a[i] = a[i],a[1] + else + a[c[i]],a[i] = a[i],a[c[i]] + end + table.insert(out, deepcopy(a)) + c[i] = c[i]+1 + i = 1 + else + c[i] = 1 + i = i+1 + end + end + return out +end + +function split(t) + local cl = {} + string.gsub(t, + "(.)", + function(c) + table.insert(cl, c) + end + ) + return cl +end + +function join(t) + local out="" + for k,v in pairs(t) do + out = out .. v + end + return out +end + +function dictionaryrank(a) + local c = split(a) + local d = {} + for _, o in ipairs(permute(c)) do + d[join(o)] = true + end + local dd = {} + for k, _ in pairs(d) do + table.insert(dd, k) + end + table.sort(dd) + for i, s in ipairs(dd) do + if s == a then + return i + end + end + return 0 +end + +if dictionaryrank("CAT") == 3 then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if dictionaryrank("GOOGLE") == 88 then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if dictionaryrank("SECRET") == 255 then + io.write("Pass") +else + io.write("FAIL") +end +print("") + diff --git a/challenge-260/roger-bell-west/perl/ch-1.pl b/challenge-260/roger-bell-west/perl/ch-1.pl new file mode 100755 index 0000000000..b644823003 --- /dev/null +++ b/challenge-260/roger-bell-west/perl/ch-1.pl @@ -0,0 +1,22 @@ +#! /usr/bin/perl + +use strict; +use warnings; +use experimental 'signatures'; + +use Test::More tests => 3; + +is(uniqueoccurrences([1, 2, 2, 1, 1, 3]), 1, 'example 1'); +is(uniqueoccurrences([1, 2, 3]), 0, 'example 2'); +is(uniqueoccurrences([-2, 0, 1, -2, 1, 1, 0, 1, -2, 9]), 1, 'example 3'); + +sub uniqueoccurrences($a) { + my %c; + map {$c{$_}++} @{$a}; + my %d = map {$_ => 1} values %c; + if (scalar keys %d == scalar keys %c) { + return 1; + } else { + return 0; + } +} diff --git a/challenge-260/roger-bell-west/perl/ch-2.pl b/challenge-260/roger-bell-west/perl/ch-2.pl new file mode 100755 index 0000000000..ca2db96207 --- /dev/null +++ b/challenge-260/roger-bell-west/perl/ch-2.pl @@ -0,0 +1,29 @@ +#! /usr/bin/perl + +use strict; +use warnings; +use experimental 'signatures'; + +use Test::More tests => 3; + +is(dictionaryrank('CAT'), 3, 'example 1'); +is(dictionaryrank('GOOGLE'), 88, 'example 2'); +is(dictionaryrank('SECRET'), 255, 'example 3'); + +use Algorithm::Combinatorics qw(permutations); + +sub dictionaryrank($a) { + my @c = split '', $a; + my %d; + my $ip = permutations(\@c); + while (my $c = $ip->next) { + $d{join('', @{$c})} = 1; + } + my @dd = sort keys %d; + foreach my $i (0 .. $#dd) { + if ($dd[$i] eq $a) { + return $i + 1; + } + } + return 0; +} diff --git a/challenge-260/roger-bell-west/postscript/ch-1.ps b/challenge-260/roger-bell-west/postscript/ch-1.ps new file mode 100644 index 0000000000..602ce57d34 --- /dev/null +++ b/challenge-260/roger-bell-west/postscript/ch-1.ps @@ -0,0 +1,91 @@ +%!PS + +% begin included library code +% see https://codeberg.org/Firedrake/postscript-libraries/ +/test.start { + print (:) print + /test.pass 0 def + /test.count 0 def +} bind def + +/test { + /test.count test.count 1 add def + { + /test.pass test.pass 1 add def + } { + ( ) print + test.count (....) cvs print + (-fail) print + } ifelse +} bind def + +/keys { % dict -> array of dict keys + [ exch + { + pop + } forall + ] +} bind def + +/values { % dict -> array of dict values + [ exch + { + exch pop + } forall + ] +} bind def + +/toset { % array -> dict of (value, true) + << exch + { + true + } forall + >> +} bind def + +/dget { + 3 1 roll + 2 copy + known { + get exch pop + } { + pop pop + } ifelse +} bind def + +/test.end { + ( ) print + test.count 0 gt { + (Passed ) print + test.pass (...) cvs print + (/) print + test.count (...) cvs print + ( \() print + test.pass 100 mul test.count idiv (...) cvs print + (%\)) print + (\r\n) print + } if +} bind def + + +% end included library code + +/uniqueoccurrences { + 0 dict begin + /c 0 dict def + { + dup c exch 0 dget 1 add c 3 1 roll put + } forall + c values toset keys length c keys length eq { + 1 + } { + 0 + } ifelse + end +} bind def + +(uniqueoccurrences) test.start +[1 2 2 1 1 3] uniqueoccurrences 1 eq test +[1 2 3] uniqueoccurrences 0 eq test +[-2 0 1 -2 1 1 0 1 -2 9] uniqueoccurrences 1 eq test +test.end diff --git a/challenge-260/roger-bell-west/postscript/ch-2.ps b/challenge-260/roger-bell-west/postscript/ch-2.ps new file mode 100644 index 0000000000..d35a2a9777 --- /dev/null +++ b/challenge-260/roger-bell-west/postscript/ch-2.ps @@ -0,0 +1,290 @@ +%!PS + +% begin included library code +% see https://codeberg.org/Firedrake/postscript-libraries/ +/test.end { + ( ) print + test.count 0 gt { + (Passed ) print + test.pass (...) cvs print + (/) print + test.count (...) cvs print + ( \() print + test.pass 100 mul test.count idiv (...) cvs print + (%\)) print + (\r\n) print + } if +} bind def + +/keys { % dict -> array of dict keys + [ exch + { + pop + } forall + ] +} bind def + +/deepeq { + 2 dict begin + /a exch def + /b exch def + a type b type eq { + a type /dicttype eq { + a length b length eq { + << + a { + pop + true + } forall + b { + pop + true + } forall + >> + true exch + { + pop + dup a exch known { + dup b exch known { + dup a exch get exch b exch get deepeq not { + pop false + } if + } { + false + } ifelse + } { + false + } ifelse + } forall + } { + false + } ifelse + } { + a type dup /arraytype eq exch /stringtype eq or { + a length b length eq { + true + 0 1 a length 1 sub { + dup a exch get exch b exch get deepeq not { + pop false + exit + } if + } for + } { + false + } ifelse + } { + a b eq + } ifelse + } ifelse + } { + false + } ifelse + end +} bind def + +/permute { % [array] {proc} permute runs proc on each permutation of array + 7 dict begin + /permute.subproc exch def + /permute.a exch def + /permute.n permute.a length def + /permute.c [ permute.n { 0 } repeat ] def + permute.a permute.subproc + /permute.i 0 def + { + permute.i permute.n ge { + exit + } if + permute.c permute.i get permute.i lt { + permute.i 2 mod 0 eq { + 0 permute.i permute.swap + } { + permute.c permute.i get permute.i permute.swap + } ifelse + permute.a permute.subproc + permute.c permute.i get 1 add permute.c exch permute.i exch put + /permute.i 0 def + } { + permute.c permute.i 0 put + /permute.i permute.i 1 add def + } ifelse + } loop + end +} bind def + +/quicksort { + { quicksort.cmp } quicksort.with_comparator +} bind def + +/quicksort.swap { + 2 dict begin + /bi exch def + /ai exch def + arr ai get + arr bi get + arr exch ai exch put + arr exch bi exch put + end +} bind def + +/quicksort.cmp { + 2 copy + lt { + pop pop -1 + } { + gt { + 1 + } { + 0 + } ifelse + } ifelse +} bind def + +/permute.swap { + /permute.bi exch def + /permute.ai exch def + permute.a permute.ai get + permute.a permute.bi get + permute.a exch permute.ai exch put + permute.a exch permute.bi exch put +} bind def + +/test { + /test.count test.count 1 add def + { + /test.pass test.pass 1 add def + } { + ( ) print + test.count (....) cvs print + (-fail) print + } ifelse +} bind def + +/enumerate.array { + 1 dict begin + /a exch def + [ + 0 1 a length 1 sub { + [ exch dup a exch get ] + } for + ] + end +} bind def + +/a2s { + 2 dict begin + /i exch def + i length dup string /o exch def + 1 sub 0 exch 1 exch { + dup i 3 -1 roll get o 3 1 roll put + } for + o + end +} bind def + +/map { % array proc -> array + 2 dict begin + /p exch def + [ exch + { + p + } forall + ] + end +} bind def + +/s2a { + [ exch { } forall ] +} bind def + +/quicksort.partition { + 3 dict begin + /pivot arr hi l