aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2022-05-30 00:33:07 +0100
committerGitHub <noreply@github.com>2022-05-30 00:33:07 +0100
commitc859a90c8c941b3ac119a6bab12c0377e126efa3 (patch)
tree7a46ec9d27f0b15e009f94932d48a6ae0875962c
parent4542da44511d2be33b479dda89d8ecf530f2f9ca (diff)
parent7b1755ea45cb3fdcbed860f82045ec95383a36c4 (diff)
downloadperlweeklychallenge-club-c859a90c8c941b3ac119a6bab12c0377e126efa3.tar.gz
perlweeklychallenge-club-c859a90c8c941b3ac119a6bab12c0377e126efa3.tar.bz2
perlweeklychallenge-club-c859a90c8c941b3ac119a6bab12c0377e126efa3.zip
Merge pull request #6177 from simbabque/challenge-166
Challenge 166
-rw-r--r--challenge-166/julien-fiegehenn/blog.txt1
-rw-r--r--challenge-166/julien-fiegehenn/perl/ch-1.pl72
-rw-r--r--challenge-166/julien-fiegehenn/perl/ch-2.pl171
-rw-r--r--challenge-166/julien-fiegehenn/perl/cpanfile2
-rw-r--r--challenge-166/julien-fiegehenn/typescript/ch-1.ts110
-rw-r--r--challenge-166/julien-fiegehenn/typescript/package-lock.json46
-rw-r--r--challenge-166/julien-fiegehenn/typescript/package.json8
-rw-r--r--challenge-166/julien-fiegehenn/typescript/tsconfig.json7
8 files changed, 417 insertions, 0 deletions
diff --git a/challenge-166/julien-fiegehenn/blog.txt b/challenge-166/julien-fiegehenn/blog.txt
new file mode 100644
index 0000000000..d7068eec45
--- /dev/null
+++ b/challenge-166/julien-fiegehenn/blog.txt
@@ -0,0 +1 @@
+https://simbabque.github.io/posts/weekly-challenge-166-github-copilot/ \ No newline at end of file
diff --git a/challenge-166/julien-fiegehenn/perl/ch-1.pl b/challenge-166/julien-fiegehenn/perl/ch-1.pl
new file mode 100644
index 0000000000..65fa003724
--- /dev/null
+++ b/challenge-166/julien-fiegehenn/perl/ch-1.pl
@@ -0,0 +1,72 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+# This is mostly written with Github Copilot. It's not the best quality code, but I wanted to give it a try. It has also helped writing this paragraph.
+
+# As an old systems programmer, whenever I needed to come up with a 32-bit number, I would reach for the tired old examples like 0xDeadBeef and 0xC0dedBad. I want more!
+# Write a program that will read from a dictionary and find 2- to 8-letter words that can be “spelled” in hexadecimal, with the addition of the following letter substitutions:
+# o ⟶ 0 (e.g., 0xf00d = “food”)
+# l ⟶ 1
+# i ⟶ 1
+# s ⟶ 5
+# t ⟶ 7
+# You can use your own dictionary or you can simply open ../../../data/dictionary.txt (relative to your script’s location in our GitHub repository) to access the dictionary of common words from Week #161.
+# Optional Extras (for an 0xAddedFee, of course!)
+# Limit the number of “special” letter substitutions in any one result to keep that result at least somewhat comprehensible. (0x51105010 is an actual example from my sample solution you may wish to avoid!)
+# Find phrases of words that total 8 characters in length (e.g., 0xFee1Face), rather than just individual words.
+
+# read the dictionary with Path::Tiny and return an array of words
+use Path::Tiny 'path';
+use feature 'say';
+
+my @dictionary = path('../../../data/dictionary.txt')->lines( { chomp => 1 } );
+
+sub find_hex_words {
+ my $dictionary = shift;
+ my @words;
+ foreach my $word (@dictionary) {
+ next if length $word < 2;
+ next if length $word > 8;
+ $word =~ tr/olist/01157/;
+
+ if ( $word =~ /^[0-9a-f]+$/ ) {
+ push @words, $word;
+ }
+ }
+ return \@words;
+}
+
+my $hex_words = find_hex_words( \@dictionary );
+
+# print a few random hex words
+say "Random hex words:";
+printf "0x%s\n", $hex_words->[ int( rand( scalar @$hex_words ) ) ] for 1 .. 5;
+
+# Limit the number of “special” letter substitutions in any one result to keep that result at least somewhat comprehensible. (0x51105010 is an actual example from my sample solution you may wish to avoid!)
+my @legible_hex_words = grep { !m/\d{2,}/ } @{ find_hex_words( \@dictionary ) };
+say "Legible hex words:";
+printf "0x%s\n", $legible_hex_words[ int( rand( scalar @legible_hex_words ) ) ]
+ for 1 .. 5;
+
+# randomly combine words from $hex_words to make 8 letter strings
+my @eight_char_phrases;
+
+# iterate through the hex words
+foreach my $hex_word (@$hex_words) {
+
+ # iterate through the hex words again
+ foreach my $hex_word2 (@$hex_words) {
+
+ # if the combination is 8 chars, use ucfist on the 2nd and push the combination
+ if ( length( $hex_word . $hex_word2 ) == 8 ) {
+ my $ucfirst = ucfirst( lc($hex_word2) );
+ push @eight_char_phrases, $hex_word . $ucfirst;
+ }
+ }
+}
+
+say "Random 8-letter phrases:";
+printf "0x%s\n",
+ $eight_char_phrases[ int( rand( scalar @eight_char_phrases ) ) ]
+ for 1 .. 5;
diff --git a/challenge-166/julien-fiegehenn/perl/ch-2.pl b/challenge-166/julien-fiegehenn/perl/ch-2.pl
new file mode 100644
index 0000000000..d56b31f449
--- /dev/null
+++ b/challenge-166/julien-fiegehenn/perl/ch-2.pl
@@ -0,0 +1,171 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use Path::Tiny 'path';
+use Text::Table::Tiny 'generate_table';
+
+### This code is generated with Github Copilot. It's not the best quality code, but I wanted to give it a try. It has also helped writing this paragraph.
+### I have mostly written the comments in this file, and then waited for it to suggest code. Sometimes I've written a variable name. It took a few
+### attempts to get it right. I think it's easier to give it very short senteces as instructions.
+
+
+# create a temporary directory structure like this:
+# dir_a:
+# Arial.ttf Comic_Sans.ttf Georgia.ttf Helvetica.ttf Impact.otf Verdana.ttf Old_Fonts/
+
+# dir_b:
+# Arial.ttf Comic_Sans.ttf Courier_New.ttf Helvetica.ttf Impact.otf Tahoma.ttf Verdana.ttf
+
+# dir_c:
+
+# create a directory dir_a;
+my $dir_a = path('dir_a');
+
+# create some files in dir a
+# Arial.ttf Comic_Sans.ttf Georgia.ttf Helvetica.ttf Impact.otf Verdana.ttf Old_Fonts/
+for my $file ( qw(Arial.ttf Comic_Sans.ttf Georgia.ttf Helvetica.ttf Impact.otf Verdana.ttf Old_Fonts/) ) {
+ $dir_a->child($file)->touchpath;
+}
+
+# dir_b:
+# Arial.ttf Comic_Sans.ttf Courier_New.ttf Helvetica.ttf Impact.otf Tahoma.ttf Verdana.ttf
+my $dir_b = path('dir_b');
+for my $file (qw(Arial.ttf Comic_Sans.ttf Courier_New.ttf Helvetica.ttf Impact.otf Tahoma.ttf Verdana.ttf)) {
+ $dir_b->child($file)->touchpath;
+}
+
+# dir_c:
+my $dir_c = path('dir_c');
+# Arial.ttf Courier_New.ttf Helvetica.ttf Impact.otf Monaco.ttf Verdana.ttf
+for my $file (qw(Arial.ttf Courier_New.ttf Helvetica.ttf Impact.otf Monaco.ttf Verdana.ttf)) {
+ $dir_c->child($file)->touchpath;
+}
+
+# clean up the temporary directory structure at the end of the program
+END {
+ $dir_a->remove_tree;
+ $dir_b->remove_tree;
+ $dir_c->remove_tree;
+}
+
+# Given a few (three or more) directories (non-recursively), display a side-by-side difference of files that are missing from at least one of the directories. Do not display files that exist in every directory.
+
+=head2 find_missing_files(@dirs)
+
+Takes a list of L<Path::Tiny> objects and returns a hashref of directories with a list of filenames that do not exist in all directories each.
+
+ my $missing_files = find_missing_files(@dirs);
+ # $missing_files = {
+ # dir_a => [qw(Comic_Sans.ttf Georgia.ttf Old_Fonts/)],
+ # dir_b => [qw(Comic_Sans.ttf Courier_New.ttf Tahoma.ttf)],
+ # dir_c => [qw(Courier_New.ttf Monaco.ttf)],
+
+=cut
+
+sub find_missing_files {
+ my @dirs = @_;
+ my %files_that_dont_exist_in_all_dirs_by_dir;
+
+ # iterate directories
+ # iterate files in each directory sorted by their filename
+ # if the filename does not exists in all directories, add the filename to the hash of files for this directory
+ for my $dir (@dirs) {
+ my @files = $dir->children;
+ for my $file (sort @files) { # I added sort
+ my $filename = $file->basename;
+ my $exists_in_all_dirs = 1;
+ for my $dir (@dirs) {
+ if (!$dir->child($filename)->exists) {
+ $exists_in_all_dirs = 0;
+ last;
+ }
+ }
+ if (!$exists_in_all_dirs) {
+ push @{$files_that_dont_exist_in_all_dirs_by_dir{$dir}}, $filename;
+ }
+ }
+ }
+
+ return \%files_that_dont_exist_in_all_dirs_by_dir;
+}
+
+my $missing = find_missing_files($dir_a, $dir_b, $dir_c);
+
+
+=head2 make_table($missing_files_by_dir)
+
+Takes a hashref of dirs, each containing a list of missing files and returns a L<Text::Table::Tiny> object.
+
+ my $table = make_table($missing_files_by_dir);
+
+The input data looks like this:
+
+ [
+ [
+ "Comic_Sans.ttf",
+ "Courier_New.ttf",
+ "Tahoma.ttf"
+ ],
+ [
+ "Courier_New.ttf",
+ "Monaco.ttf"
+ ],
+ [
+ "Comic_Sans.ttf",
+ "Georgia.ttf",
+ "Old_Fonts"
+ ]
+ ]
+
+The table has one column per directory, and one row per file. The rows are sorted by filename.
+If a file is missing from a directory, the cell is empty.
+
+ dir_a | dir_b | dir_c
+ -------------- | --------------- | ---------------
+ Comic_Sans.ttf | Comic_Sans.ttf |
+ | Courier_New.ttf | Courier_New.ttf
+ Georgia.ttf | |
+ | | Monaco.ttf
+ Old_Fonts/ | |
+ | Tahoma.ttf |
+
+=cut
+
+sub make_table {
+ my $missing_files_by_dir = shift;
+
+ use List::Util qw(uniq);
+ # get all unique elements of all the arrays in the hash and sort them alphabetically
+ my @files_in_all_dirs = uniq map { @$_ } values %$missing_files_by_dir;
+ my @dirs = sort keys %$missing_files_by_dir;
+
+ my $table = generate_table(
+ rows => [
+ [ @dirs ],
+ # iterate the files
+ # iterate the directories for each file
+ # check if the file exists in the directory
+ # if it does, add the filename to the row
+ # if it does not, add an empty cell
+ map {
+ my $filename = $_;
+ my @row;
+ for my $dir (@dirs) {
+ if (grep { $_ eq $filename } @{$missing_files_by_dir->{$dir}}) {
+ push @row, $filename;
+ }
+ else {
+ push @row, '';
+ }
+ }
+ [ @row ];
+ } sort @files_in_all_dirs
+ ],
+ header_row => 1,
+ );
+
+ return $table;
+}
+
+print make_table($missing);
diff --git a/challenge-166/julien-fiegehenn/perl/cpanfile b/challenge-166/julien-fiegehenn/perl/cpanfile
new file mode 100644
index 0000000000..d2d1d997ed
--- /dev/null
+++ b/challenge-166/julien-fiegehenn/perl/cpanfile
@@ -0,0 +1,2 @@
+requires 'Path::Tiny';
+requires 'Text::Table::Tiny'; \ No newline at end of file
diff --git a/challenge-166/julien-fiegehenn/typescript/ch-1.ts b/challenge-166/julien-fiegehenn/typescript/ch-1.ts
new file mode 100644
index 0000000000..f8bf35c30e
--- /dev/null
+++ b/challenge-166/julien-fiegehenn/typescript/ch-1.ts
@@ -0,0 +1,110 @@
+// As an old systems programmer, whenever I needed to come up with a 32-bit number, I would reach for the tired old examples like 0xDeadBeef and 0xC0dedBad. I want more!
+
+// Write a program that will read from a dictionary and find 2- to 8-letter words that can be “spelled” in hexadecimal, with the addition of the following letter substitutions:
+
+// o ⟶ 0 (e.g., 0xf00d = “food”)
+// l ⟶ 1
+// i ⟶ 1
+// s ⟶ 5
+// t ⟶ 7
+// You can use your own dictionary or you can simply open ../../../data/dictionary.txt (relative to your script’s location in our GitHub repository) to access the dictionary of common words from Week #161.
+
+// Optional Extras (for an 0xAddedFee, of course!)
+// Limit the number of “special” letter substitutions in any one result to keep that result at least somewhat comprehensible. (0x51105010 is an actual example from my sample solution you may wish to avoid!)
+// Find phrases of words that total 8 characters in length (e.g., 0xFee1Face), rather than just individual words.
+
+// read the dictionary and return an array of words
+function readDictionary(fileName: string): string[] {
+ const fs = require("fs");
+ const dictionary = fs.readFileSync(fileName, "utf8").split("\n");
+ return dictionary;
+}
+
+// Write a program that will read from a dictionary and find 2- to 8-letter words that can be “spelled” in hexadecimal, with the addition of the following letter substitutions:
+function findWords(dictionary: string[], wordLength: number): string[] {
+ const hexWords = [];
+ const hexLetters = {
+ o: "0",
+ l: "1",
+ i: "1",
+ s: "5",
+ t: "7",
+ };
+ const hexLettersRegex = new RegExp(Object.keys(hexLetters).join("|"), "g");
+ for (let i = 0; i < dictionary.length; i++) {
+ if (dictionary[i].length === wordLength) {
+ let hexWord = dictionary[i].toLowerCase();
+ hexWord = hexWord.replace(
+ hexLettersRegex,
+ (letter) => hexLetters[letter]
+ );
+ hexWord = hexWord.replace(/[^0-9a-f]/g, "");
+ if (hexWord.length === wordLength) {
+ // I changed this line, it wanted to compare to wordLength * 2
+ hexWords.push(hexWord);
+ }
+ }
+ }
+ return hexWords;
+}
+
+// use readDictionary, iterate 2 to 8 and findWords
+function findWordsInHex(dictionary: string[], wordLength: number): string[] {
+ const hexWords = [];
+ for (let i = 2; i <= wordLength; i++) {
+ hexWords.push(...findWords(dictionary, i));
+ }
+ return hexWords;
+}
+
+console.log(findWordsInHex(readDictionary("../../../data/dictionary.txt"), 8));
+
+const allHexWords: string[] = findWordsInHex(
+ readDictionary("../../../data/dictionary.txt"),
+ 8
+);
+// output the last 10 hex words
+console.log(allHexWords.slice(-10));
+
+// find combinations of words from allHexWords that do not exceed 8 characters and combine them in camelCase
+function findCamelCaseWords(allHexWords: string[]): string[] {
+ const camelCaseWords = [];
+ for (let i = 0; i < allHexWords.length; i++) {
+ for (let j = 0; j < allHexWords.length; j++) {
+ if (allHexWords[i].length + allHexWords[j].length <= 8) {
+ camelCaseWords.push(
+ allHexWords[i] +
+ allHexWords[j].charAt(0).toUpperCase() +
+ allHexWords[j].slice(1)
+ );
+ }
+ }
+ }
+ return camelCaseWords;
+}
+
+// print 5 random camelcase words
+console.log(
+ findCamelCaseWords(allHexWords)
+ .sort(() => 0.5 - Math.random())
+ .slice(0, 5)
+);
+
+// ignore words from allHexWords that have consecutive 1s
+function ignoreConsecutiveOnes(allHexWords: string[]): string[] {
+ const camelCaseWords = [];
+ for (let i = 0; i < allHexWords.length; i++) {
+ if (!/1{2,}/.test(allHexWords[i])) {
+ camelCaseWords.push(allHexWords[i]);
+ }
+ }
+ return camelCaseWords;
+}
+
+// print 5 random strings from allhexwords that ignore consecutive 1s
+console.log(
+ ignoreConsecutiveOnes(allHexWords)
+ .sort(() => 0.5 - Math.random())
+ .slice(0, 5)
+);
+
diff --git a/challenge-166/julien-fiegehenn/typescript/package-lock.json b/challenge-166/julien-fiegehenn/typescript/package-lock.json
new file mode 100644
index 0000000000..a490c9abb1
--- /dev/null
+++ b/challenge-166/julien-fiegehenn/typescript/package-lock.json
@@ -0,0 +1,46 @@
+{
+ "name": "typescript",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "dependencies": {
+ "typescript": "^4.7.2"
+ },
+ "devDependencies": {
+ "@types/node": "^17.0.36"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "17.0.36",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.36.tgz",
+ "integrity": "sha512-V3orv+ggDsWVHP99K3JlwtH20R7J4IhI1Kksgc+64q5VxgfRkQG8Ws3MFm/FZOKDYGy9feGFlZ70/HpCNe9QaA==",
+ "dev": true
+ },
+ "node_modules/typescript": {
+ "version": "4.7.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.2.tgz",
+ "integrity": "sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ }
+ },
+ "dependencies": {
+ "@types/node": {
+ "version": "17.0.36",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.36.tgz",
+ "integrity": "sha512-V3orv+ggDsWVHP99K3JlwtH20R7J4IhI1Kksgc+64q5VxgfRkQG8Ws3MFm/FZOKDYGy9feGFlZ70/HpCNe9QaA==",
+ "dev": true
+ },
+ "typescript": {
+ "version": "4.7.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.2.tgz",
+ "integrity": "sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A=="
+ }
+ }
+}
diff --git a/challenge-166/julien-fiegehenn/typescript/package.json b/challenge-166/julien-fiegehenn/typescript/package.json
new file mode 100644
index 0000000000..06c72efaa1
--- /dev/null
+++ b/challenge-166/julien-fiegehenn/typescript/package.json
@@ -0,0 +1,8 @@
+{
+ "dependencies": {
+ "typescript": "^4.7.2"
+ },
+ "devDependencies": {
+ "@types/node": "^17.0.36"
+ }
+}
diff --git a/challenge-166/julien-fiegehenn/typescript/tsconfig.json b/challenge-166/julien-fiegehenn/typescript/tsconfig.json
new file mode 100644
index 0000000000..3e3ab9fae8
--- /dev/null
+++ b/challenge-166/julien-fiegehenn/typescript/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "compilerOptions": {
+ "target": "ES6",
+ "module": "CommonJS",
+ "lib": ["ES6", "DOM"]
+ }
+} \ No newline at end of file