aboutsummaryrefslogtreecommitdiff
path: root/challenge-007
diff options
context:
space:
mode:
authorDavid Ferrone <zapwai@gmail.com>2024-03-15 11:21:15 -0400
committerDavid Ferrone <zapwai@gmail.com>2024-03-15 11:21:15 -0400
commit60c68b3209b3c09d3cbd29b4ef33080546a43fbd (patch)
tree48d43fa4f9c8ea2492e7ab11146b7df7bb1a1679 /challenge-007
parent2a68a16c1d8727b183d85c88f31ae6cec6a869b1 (diff)
downloadperlweeklychallenge-club-60c68b3209b3c09d3cbd29b4ef33080546a43fbd.tar.gz
perlweeklychallenge-club-60c68b3209b3c09d3cbd29b4ef33080546a43fbd.tar.bz2
perlweeklychallenge-club-60c68b3209b3c09d3cbd29b4ef33080546a43fbd.zip
Weekly Challenge Blast from the Past
Diffstat (limited to 'challenge-007')
-rw-r--r--challenge-007/zapwai/README1
-rw-r--r--challenge-007/zapwai/c/ch-1.c19
-rw-r--r--challenge-007/zapwai/c/ch-2.c399
-rw-r--r--challenge-007/zapwai/javascript/ch-1.js10
-rw-r--r--challenge-007/zapwai/javascript/ch-2.js176
-rw-r--r--challenge-007/zapwai/perl/ch-1.pl8
-rw-r--r--challenge-007/zapwai/perl/ch-2.pl120
-rw-r--r--challenge-007/zapwai/python/ch-1.py9
-rw-r--r--challenge-007/zapwai/python/ch-2.py132
-rw-r--r--challenge-007/zapwai/rust/ch-1.rs15
-rw-r--r--challenge-007/zapwai/rust/ch-2.rs175
11 files changed, 1064 insertions, 0 deletions
diff --git a/challenge-007/zapwai/README b/challenge-007/zapwai/README
new file mode 100644
index 0000000000..037b3777ef
--- /dev/null
+++ b/challenge-007/zapwai/README
@@ -0,0 +1 @@
+Solutions by David Ferrone.
diff --git a/challenge-007/zapwai/c/ch-1.c b/challenge-007/zapwai/c/ch-1.c
new file mode 100644
index 0000000000..5b17e2361f
--- /dev/null
+++ b/challenge-007/zapwai/c/ch-1.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <stdbool.h>
+
+bool is_niven(int i) {
+ int num = i;
+ int tally = 0;
+ while (num > 0) {
+ tally += num % 10;
+ num /= 10;
+ }
+ return (i % tally == 0);
+}
+
+int main() {
+ for (int i = 1; i < 51; i++) {
+ if (is_niven(i))
+ printf("%d\n", i);
+ }
+}
diff --git a/challenge-007/zapwai/c/ch-2.c b/challenge-007/zapwai/c/ch-2.c
new file mode 100644
index 0000000000..5582b819e9
--- /dev/null
+++ b/challenge-007/zapwai/c/ch-2.c
@@ -0,0 +1,399 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <regex.h>
+
+#define max_length 50
+#define thou 50000
+#define rows_in_file 50000 /* using a custom word file w 38k words */
+#define limit 5 /* max chain length is twice limit */
+
+char** read_file(char* filename, int* num_words) {
+ FILE* fp = fopen(filename, "r");
+ if (fp == NULL) return NULL;
+ char** words = malloc(rows_in_file * sizeof(char*));
+ if (words == NULL) return NULL;
+ char buffer[max_length];
+ int i = 0;
+ while (fgets(buffer, max_length, fp) != NULL) {
+ words[i] = malloc(max_length * sizeof(char));
+ if (words[i] == NULL) return NULL;
+ strcpy(words[i], buffer);
+ i++;
+ }
+ fclose(fp);
+ *num_words = i;
+ return words;
+}
+
+void chomp(char** words) {
+ for (int i = 0; words[i] != NULL; i++) {
+ char* str = words[i];
+ size_t len = strlen(str);
+ if (len > 0 && str[len - 1] == '\n')
+ str[len - 1] = '\0';
+ }
+}
+
+void push(char** list, char* item, int i) {
+ list[i] = malloc(max_length * sizeof(char));
+ strcpy(list[i], item);
+}
+
+void unshift(char** list, char* item, int len) {
+ list[len] = malloc(max_length * sizeof(char));
+ for (int i = len; i > 0; i--)
+ strcpy(list[i], list[i - 1]);
+ strcpy(list[0], item);
+}
+
+char** unique(char** words, int words_length, int* uniq_len) {
+ char** subset = malloc(thou * sizeof(char*));
+ for (int i = 0; i < thou; i++)
+ subset[i] = malloc(max_length * sizeof(char));
+ int k = 0;
+ for (int i = 0; i < words_length; i++) {
+ bool flag = false;
+ for (int j = 0; j < k; j++)
+ if (strcmp(words[i], subset[j]) == 0) {
+ flag = true;
+ break;
+ }
+ if (!flag) {
+ strcpy(subset[k], words[i]);
+ k++;
+ }
+ }
+ *uniq_len = k;
+ return subset;
+}
+
+char** intersection(char** list1, char** list2, int l1_len, int l2_len, int* hits) {
+ char** common = malloc(thou * sizeof(char*));
+ int k = 0;
+ for (int i = 0; i < l1_len; i++) {
+ for (int j = 0; j < l2_len; j++) {
+ if (0 == strcmp(list1[i], list2[j])) {
+ common[k] = malloc(max_length * sizeof(char));
+ strcpy(common[k], list1[i]);
+ k++;
+ }
+ }
+ }
+ *hits = k;
+ return common;
+}
+
+void check(int m, int n, char*** A, char*** B, int* Acnt, int* Bcnt, char** center) {
+ char** ans = malloc(thou * sizeof(char*));
+ for (int i = 0; i < thou; i++)
+ ans[i] = malloc(max_length * sizeof(char));
+ int k = 0;
+ for (int i = 0; i < m; i++)
+ for (int j = 0; j < n; j++) {
+ int hits = 0;
+ char** common = intersection(A[i], B[j], Acnt[i], Bcnt[j], &hits);
+ for (int l = 0; l < hits; l++) {
+ strcpy(ans[k], common[l]);
+ k++;
+ }
+ for (int l = 0; l < hits; l++)
+ free(common[l]);
+ free(common);
+ }
+
+ for (int i = 0; i < k; i++)
+ strcpy(center[i], ans[i]);
+ for (int i = 0; i < thou; i++)
+ free(ans[i]);
+ free(ans);
+}
+
+char** expand(char* word, char** words, int* length) {
+ char** new = malloc(thou * sizeof(char*));
+ for (int i = 0; i < thou; i++)
+ new[i] = malloc(max_length * sizeof(char));
+ int k = 0;
+ for (int i = 0; i < strlen(word); i++) {
+ char pre[max_length] = {};
+ char post[max_length] = {};
+ strncpy(pre, word, i);
+ strncpy(post, word + i + 1, strlen(word) - i);
+ char rexp[max_length] = {};
+ strcat(rexp, pre);
+ strcat(rexp, ".");
+ strcat(rexp, post);
+ regex_t regex;
+ int ret = regcomp(&regex, rexp, REG_EXTENDED);
+ if (ret != 0){
+ fprintf(stderr, "failure to compile the regex.\n");
+ return NULL;
+ }
+ for (int j = 0; words[j] != NULL; j++) {
+ ret = regexec(&regex, words[j], 0, NULL, 0);
+ if (ret == 0) {
+ if (0 != strcmp(words[j], word)) {
+ strcpy(new[k],words[j]);
+ k++;
+ }
+ }
+ }
+ regfree(&regex);
+ }
+ *length = k;
+ return new;
+}
+
+int dist(char* word1, char* word2) {
+ int cnt = 0;
+ for (int i = 0; i < strlen(word1); i++)
+ if (word1[i] != word2[i])
+ cnt++;
+ return cnt;
+}
+
+char* neighbor(char* word, char** word_list) {
+ for (int i = 0; word_list[i] != NULL; i++)
+ if (1 == dist(word, word_list[i]))
+ return word_list[i];
+ return NULL;
+}
+
+char** grep_for_length(size_t length, char** dict, int* words_len) {
+ char** words = malloc(rows_in_file*sizeof(char*));
+ for (int i = 0; i < rows_in_file; i++)
+ words[i] = malloc(max_length*sizeof(char));
+ int k = 0;
+ for (int i = 0; dict[i] != NULL; i++) {
+ if (strlen(dict[i]) == length){
+ strcpy(words[k],dict[i]);
+ k++;
+ }
+ }
+ *words_len = k;
+ return words;
+}
+
+char*** neighbors_container() {
+ char*** A = malloc(limit * sizeof(char**));
+ for (int i = 0; i < limit; i++) {
+ A[i] = malloc(thou * sizeof(char*));
+ }
+ return A;
+}
+
+void clean_cycle(char** a_uniq, char** b_uniq, char** anew, char** bnew) {
+ for (int i = 0; i < thou; i++) {
+ free(a_uniq[i]);
+ free(b_uniq[i]);
+ free(anew[i]);
+ free(bnew[i]);
+ }
+ free(a_uniq);
+ free(b_uniq);
+ free(anew);
+ free(bnew);
+}
+
+void cleanup(char** list, char*** A, char*** B, char** center, char** words, int words_len, int list_len, int* Acnt, int* Bcnt) {
+ for (int j = 0; j < list_len; j++)
+ free(list[j]);
+ free(list);
+ for (int j = 0; j < thou; j++)
+ free(center[j]);
+ free(center);
+ for (int i = 0; i < limit; i++) {
+ for (int j = 0; j < Acnt[i]; j++)
+ free(A[i][j]);
+ for (int j = 0; j < Bcnt[i]; j++)
+ free(B[i][j]);
+
+ free(A[i]);
+ free(B[i]);
+ }
+ free(A);
+ free(B);
+
+ for (int i = 0; i < words_len; i++)
+ free(words[i]);
+ free(words);
+}
+
+void proc(char** dict, int dict_len, char* input1, char* input2) {
+ printf("Input: %s to %s\n", input1, input2);
+
+ if (strlen(input1) != strlen(input2)) {
+ printf("Output: ()\n");
+ printf("[Lengths are not equal.]\n");
+ return;
+ }
+
+ int cnt = 0;
+ for (int i = 0; i < dict_len; i++)
+ if ((0 == strcmp(input1, dict[i])) || (0 == strcmp(input2, dict[i])))
+ cnt++;
+ if (cnt < 2) {
+ printf("Output: ()\n");
+ printf("[One of these inputs is not considered a word.]\n");
+ return;
+ }
+
+ int words_len;
+ char** words = grep_for_length(strlen(input1), dict, &words_len);
+
+ /* A[1] contains words a distance 1 from input1, A[2] dist 2, etc. */
+ char*** A = neighbors_container();
+ char*** B = neighbors_container();
+ A[0][0] = malloc(max_length * sizeof(char));
+ B[0][0] = malloc(max_length * sizeof(char));
+ strcpy(A[0][0], input1);
+ strcpy(B[0][0], input2);
+
+ /* these record the number of cells at each level of A or B */
+ int Acnt[limit] = {};
+ int Bcnt[limit] = {};
+ Acnt[0] = 1;
+ Bcnt[0] = 1;
+
+ int lvl = 0;
+
+ char** center = malloc(thou * sizeof(char*));
+ for (int i = 0; i < thou; i++)
+ center[i] = malloc(max_length * sizeof(char));
+
+ do {
+ char** anew = malloc(thou *sizeof(char*));
+ char** bnew = malloc(thou *sizeof(char*));
+ for (int i = 0; i < thou; i++) {
+ anew[i] = malloc(max_length * sizeof(char));
+ bnew[i] = malloc(max_length * sizeof(char));
+ }
+
+ int k = 0;
+ for (int i = 0; i < Acnt[lvl]; i++) {
+ int temp_length;
+ char** temp = expand(A[lvl][i], words, &temp_length);
+ if (temp_length == 0) {
+ printf("Output: ()\n");
+ printf("[No neighboring words on %s.]\n", A[lvl][i]);
+ return;
+ }
+ for (int j = 0; j < temp_length; j++) {
+ strcpy(anew[k], temp[j]);
+ k++;
+ }
+ for (int l = 0; l < thou; l++)
+ free(temp[l]);
+ free(temp);
+ }
+ int anew_length = k;
+
+ /* Check if they're already neighbors. */
+ for (int i = 0; i < anew_length; i++) {
+ if (0 == strcmp(anew[i], input2)) {
+ printf("Output: %s %s\n", input1, input2);
+ return;
+ }
+ }
+
+ k = 0;
+ for (int i = 0; i < Bcnt[lvl]; i++) {
+ int temp_length;
+ char** temp = expand(B[lvl][i], words, &temp_length);
+ if (temp_length == 0) {
+ printf("Output: ()\n");
+ printf("[No neighboring words on %s.]\n", B[lvl][i]);
+ return;
+ }
+
+ for (int j = 0; j < temp_length; j++) {
+ strcpy(bnew[k], temp[j]);
+ k++;
+ }
+ for (int l = 0; l < thou; l++)
+ free(temp[l]);
+ free(temp);
+ }
+ int bnew_length = k;
+
+ int a_uniq_len = 0;
+ int b_uniq_len = 0;
+ char** a_uniq = unique(anew, anew_length, &a_uniq_len);
+ char** b_uniq = unique(bnew, bnew_length, &b_uniq_len);
+
+ for (int i = 0; i < a_uniq_len; i++)
+ push(A[lvl+1], a_uniq[i], i);
+ Acnt[lvl + 1] = a_uniq_len;
+
+ check(lvl + 1, lvl, A, B, Acnt, Bcnt, center);
+ if (strlen(center[0]) > 0)
+ break;
+ for (int i = 0; i < b_uniq_len; i++)
+ push(B[lvl+1], b_uniq[i], i);
+ Bcnt[lvl + 1] = b_uniq_len;
+
+ clean_cycle(a_uniq, b_uniq, anew, bnew);
+ lvl++;
+ check(lvl, lvl, A, B, Acnt, Bcnt, center);
+ if (strlen(center[0]) > 0)
+ break;
+
+ } while (lvl < limit);
+
+ if (lvl == limit) {
+ printf("Output: ()\n");
+ return;
+ }
+
+ int counter = lvl - 1;
+ char* x = neighbor(center[0], A[counter]);
+ char* y = neighbor(center[0], B[counter]);
+ char** list = malloc(thou * sizeof(char*));
+ int list_len = 0;
+ if (y != NULL) {
+ do {
+ unshift(list, x, list_len);
+ list_len++;
+ push(list, y, list_len);
+ list_len++;
+ counter--;
+ x = neighbor(x, A[counter]);
+ y = neighbor(y, B[counter]);
+ } while (counter > 0);
+ }
+ if (x != NULL) {
+ unshift(list, x, list_len);
+ list_len++;
+ }
+ if (y != NULL) {
+ push(list, y, list_len);
+ list_len++;
+ }
+
+ printf("Output: ");
+ for (int i = 0; i < list_len; i++)
+ printf("%s ", list[i]);
+ printf("\n");
+
+ cleanup(list, A, B, center, words, words_len, list_len, Acnt, Bcnt);
+}
+
+int main(int argc, char* argv[]) {
+ char* filename = "words";
+ int dict_len;
+ char** dict = read_file(filename, &dict_len);
+ chomp(dict);
+
+ char* l1[] = {"pour", "cold", "peer", "knife", "prince"};
+ char* l2[] = {"made", "warm", "norm", "dance", "prance"};
+ int len = sizeof(l1)/sizeof(char*);
+ for (int i = 0; i < len; i++)
+ proc(dict, dict_len, l1[i], l2[i]);
+
+ for (int i = 0; i < dict_len; i++)
+ free(dict[i]);
+ free(dict);
+ return 0;
+}
+
diff --git a/challenge-007/zapwai/javascript/ch-1.js b/challenge-007/zapwai/javascript/ch-1.js
new file mode 100644
index 0000000000..16830a8118
--- /dev/null
+++ b/challenge-007/zapwai/javascript/ch-1.js
@@ -0,0 +1,10 @@
+for (let i = 1; i < 51; i++) {
+ let num = i;
+ let tally = 0;
+ while (num > 0) {
+ tally += num % 10;
+ num = Math.floor(num / 10);
+ }
+ if (i % tally == 0)
+ console.log(i);
+}
diff --git a/challenge-007/zapwai/javascript/ch-2.js b/challenge-007/zapwai/javascript/ch-2.js
new file mode 100644
index 0000000000..2f07586286
--- /dev/null
+++ b/challenge-007/zapwai/javascript/ch-2.js
@@ -0,0 +1,176 @@
+let dict, word1, word2, ladder;
+const ourParagraph = document.getElementById('ourParagraph');
+const ourParagraph2 = document.getElementById('ourParagraph2');
+const fileInput = document.getElementById('fileInput');
+fileInput.addEventListener('change', handleFileUpload);
+const ourWord = document.getElementById('ourWord');
+ourWord.addEventListener('change', onWordChange);
+const ourWord2 = document.getElementById('ourWord2');
+ourWord2.addEventListener('change', onWord2Change);
+
+function onWordChange(event) {
+ word1 = event.target.value;
+ display();
+}
+
+function onWord2Change(event) {
+ word2 = event.target.value;
+ display();
+}
+
+function handleFileUpload(event) {
+ const file = event.target.files[0];
+ if (!file) {
+ console.error('No file selected');
+ return;
+ }
+ const reader = new FileReader();
+ reader.onload = function(e) {
+ const content = e.target.result;
+ const words = content.split(/\s+/);
+ dict = words;
+ getLadder();
+ display2();
+ };
+ reader.readAsText(file);
+}
+
+function quit() {
+ console.log("Output: ()");
+}
+
+function neighbor(word, word_list) {
+ for (let w of word_list)
+ if (dist(w, word) == 1)
+ return w;
+}
+
+function dist(wrd1, wrd2) {
+ let cnt = 0;
+ let w1 = wrd1.split('');
+ let w2 = wrd2.split('');
+ for (let i = 0; i < w1.length; i++)
+ if (w1[i] != w2[i])
+ cnt++;
+ return cnt;
+}
+
+function check(m, n, A, B) {
+ let ans = [];
+ for (let i = 0; i <= m; i++)
+ for (let j = 0; j <= n; j++){
+ let a = intersection(A[i], B[j]);
+ if (a.length > 0)
+ for (let e of a)
+ ans.push(e);
+ }
+ return ans;
+}
+
+function expand(word, words) {
+ let new1 = [];
+ for (let i = 0; i < word.length; i++) {
+ let pre = word.slice(0, i);
+ let post = word.slice(i+1);
+ for (let w of words) {
+ let pat = new RegExp(pre + "." + post);
+ if (pat.test(w))
+ new1.push(w);
+ }
+ }
+ let anew = new1; // filter for not eq to word
+ return anew;
+}
+
+function intersection(A, B) {
+ let ints = [];
+ for (let i = 0; i < A.length; i++)
+ for (let j = 0; j < B.length; j++)
+ if (A[i] == B[j])
+ ints.push(A[i]);
+ return ints;
+}
+
+function proc(input1, input2) {
+ let limit = 4;
+ console.log("Input:", input1, input2);
+ if (input1.length != input2.length)
+ return quit();
+ let cnt = 0;
+
+ for (let word of dict){
+ let reg1 = new RegExp(input1);
+ let reg2 = new RegExp(input2);
+ if (reg1.test(word) || reg2.test(word))
+ cnt++;
+ }
+
+ if (cnt < 2)
+ return quit();
+
+ let wordlen = input1.length;
+ let words = []
+ for (let d of dict)
+ if (d.length == wordlen)
+ words.push(d);
+ let A = [[input1]]
+ let B = [[input2]]
+ let center = []
+ let lvl = 0;
+ while (lvl < limit && center.length == 0) {
+ let anew = [];
+ let bnew = [];
+ for (let wa of A[lvl])
+ for (let w of expand(wa, words))
+ anew.push(w);
+ for (let wb of B[lvl])
+ for (let w of expand(wb, words))
+ bnew.push(w);
+ let uniq_a = [];
+ let uniq_b = [];
+ for (let item of anew)
+ if (!(item in uniq_a))
+ uniq_a.push(item);
+ for (let item of bnew)
+ if (!(item in uniq_b))
+ uniq_b.push(item);
+ A.push(uniq_a);
+ B.push(uniq_b);
+ lvl++;
+ center = check(lvl, lvl, A, B);
+ }
+ if (lvl == limit)
+ return quit();
+ let counter = lvl - 1;
+ let mylist = [center[0]];
+ let x = neighbor(center[0], A[counter]);
+ let y = neighbor(center[0], B[counter]);
+ if (y != null) {
+ while (counter > 0) {
+ mylist.unshift(x);
+ mylist.push(y);
+ counter--;
+ x = neighbor(x, A[counter]);
+ y = neighbor(y, B[counter]);
+ }
+ }
+ if (x != null)
+ mylist.unshift(x);
+ if (y != null)
+ mylist.push(y);
+ console.log("Output:", mylist);
+}
+
+function getLadder() {
+ console.log("dictionary loaded");
+ proc(word1, word2);
+}
+
+function display() {
+ ourParagraph.innerHTML = `word1: ${word1}<br>word2: ${word2}<br>`;
+}
+
+function display2() {
+ ourParagraph2.innerHTML = `${dict}`;
+}
+
diff --git a/challenge-007/zapwai/perl/ch-1.pl b/challenge-007/zapwai/perl/ch-1.pl
new file mode 100644
index 0000000000..10a5aca220
--- /dev/null
+++ b/challenge-007/zapwai/perl/ch-1.pl
@@ -0,0 +1,8 @@
+use v5.36;
+use List::Util qw( sum );
+for my $num (1 .. 50) {
+ say $num if is_niven($num);
+}
+sub is_niven ($num) {
+ $num % (sum split("", $num)) == 0
+}
diff --git a/challenge-007/zapwai/perl/ch-2.pl b/challenge-007/zapwai/perl/ch-2.pl
new file mode 100644
index 0000000000..2473c77f5d
--- /dev/null
+++ b/challenge-007/zapwai/perl/ch-2.pl
@@ -0,0 +1,120 @@
+use v5.38;
+use List::MoreUtils qw(uniq);
+
+my @l1 = ("pour", "cold", "peer", "knife", "prince");
+my @l2 = ("made", "warm", "norm", "dance", "prance");
+my %h = map { $l1[$_], $l2[$_] } (0 .. $#l1);
+proc($_,$h{$_}) foreach (keys %h);
+
+sub quit() {print "()\n"; 1}
+
+sub proc($input1, $input2) {
+ say "Input: $input1 - $input2";
+ print "Output: ";
+
+ return quit() unless (length $input1 == length $input2);
+
+ open my $fh, "<", "words";
+ my @rows = <$fh>;
+ close $fh;
+
+ return quit() unless grep { /^$input1$/ } @rows;
+ return quit() unless grep { /^$input2$/ } @rows;
+
+ my $wordlen = length $input1;
+ our @words = grep { /^\w{$wordlen}$/ } @rows;
+ chomp @words;
+
+ our @A = ([$input1]);
+ our @B = ([$input2]);
+ my $lvl = 0;
+ my $limit = 10; # (max chain length is 2*limit)
+ my @center;
+ do {
+ my (@anew, @bnew);
+ push @anew, @{expand($_)} foreach (@{$A[$lvl]});
+ push @bnew, @{expand($_)} foreach (@{$B[$lvl]});
+ @anew = uniq @anew;
+ @bnew = uniq @bnew;
+ push @A, \@anew;
+ @center = check($lvl + 1, $lvl);
+ push @B, \@bnew;
+ $lvl++;
+ } until (@center or @center = check($lvl, $lvl) or $lvl == $limit);
+
+ return quit() if ($lvl == $limit);
+
+ my $counter = $lvl - 1;
+ my @list = ($center[0]);
+ my $x = neighbor($center[0], $A[$counter]);
+ my $y = neighbor($center[0], $B[$counter]);
+ if ($y) {
+ do {
+ unshift @list, $x;
+ push @list, $y;
+ $counter--;
+ $x = neighbor($x, $A[$counter]);
+ $y = neighbor($y, $B[$counter]);
+ } until ($counter == 0);
+ }
+ unshift @list, $x;
+ push @list, $y;
+
+ say "@list";
+
+ # returns first neighbor of $word in @$ref
+ sub neighbor($word, $ref) {
+ for my $w (@$ref) {
+ if (dist($w, $word) == 1) {
+ return $w;
+ }
+ }
+ }
+
+ sub dist($word1, $word2) {
+ my @let1 = split "", $word1;
+ my @let2 = split "", $word2;
+ my $cnt = 0;
+ for my $i (0 .. $#let1) {
+ $cnt++ if ($let1[$i] ne $let2[$i]);
+ }
+ $cnt
+ }
+
+ sub check($m, $n) {
+ my @ans;
+ for my $i (0 .. $m) {
+ for my $j (0 .. $n) {
+ push @ans, intersection($A[$i], $B[$j]);
+ }
+ }
+ return @ans;
+ }
+
+ sub expand($word) {
+ my @new;
+ for my $i (0 .. (length $word) - 1) {
+ my ($pre, $post) = (substr($word, 0, $i), substr($word, $i+1));
+ foreach (grep { $_ =~ /^$pre.$post$/ } @words) {
+ push @new, $_;
+ }
+ }
+ @new = grep { !($_ eq $word) } @new;
+ return \@new;
+ }
+
+ sub intersection($r, $s) {
+ my @int;
+ my @A = @$r;
+ my @B = @$s;
+ for my $i (0 .. $#A) {
+ for my $j (0 .. $#B) {
+ if ($A[$i] eq $B[$j]) {
+ push @int, $A[$i];
+ }
+ }
+ }
+ return @int;
+ }
+
+}
diff --git a/challenge-007/zapwai/python/ch-1.py b/challenge-007/zapwai/python/ch-1.py
new file mode 100644
index 0000000000..cf326d1c3a
--- /dev/null
+++ b/challenge-007/zapwai/python/ch-1.py
@@ -0,0 +1,9 @@
+def niven(n):
+ for i in range(1, n+1):
+ tally = 0
+ digit = list(str(i))
+ for j in range(len(digit)):
+ tally += int(digit[j])
+ if i % tally == 0:
+ print(i)
+niven(51)
diff --git a/challenge-007/zapwai/python/ch-2.py b/challenge-007/zapwai/python/ch-2.py
new file mode 100644
index 0000000000..cd816028fc
--- /dev/null
+++ b/challenge-007/zapwai/python/ch-2.py
@@ -0,0 +1,132 @@
+import re
+
+def quit():
+ print("Output: ()")
+
+def read_file(filename):
+ fh = open(filename, "r")
+ words = []
+ for x in fh:
+ y = x.rstrip('\r\n');
+ words.append(y)
+ return words
+
+def neighbor(word, word_list):
+ for w in word_list:
+ if dist(w, word) == 1:
+ return w
+
+def dist(word1, word2):
+ cnt = 0
+ for i in range(len(word1)):
+ if word1[i] != word2[i]:
+ cnt += 1
+ return cnt
+
+def check(m, n, A, B):
+ ans = []
+ for i in range(m+1):
+ for j in range(n+1):
+ a = intersection(A[i], B[j])
+ if len(a) > 0:
+ for ick in a:
+ ans.append(ick)
+ return ans
+
+def expand(word, words):
+ new = []
+ for i in range(len(word)):
+ pre = word[0:i]
+ post = word[i+1:]
+ for w in words:
+ pattern = str(pre) + "." + str(post)
+ if re.search(pattern, w):
+ new.append(w)
+
+ anew = [item for item in new if item != word]
+ return anew
+
+
+def intersection(A, B):
+ int = []
+ for i in range(len(A)):
+ for j in range(len(B)):
+ if A[i] == B[j]:
+ int.append(A[i])
+ return int
+
+def proc(input1, input2):
+ limit = 4 # max-length of chain is 2*limit
+
+ print("Input:", input1, input2)
+ if len(input1) != len(input2):
+ return quit()
+ filename = "words"
+ dicts = read_file(filename)
+
+ cnt = 0
+ for word in dicts:
+ if re.search("^"+input2+"$", word) or re.search("^"+input1+"$", word):
+ cnt += 1
+ if cnt < 2:
+ print("One of these inputs is not a word.")
+ return quit()
+
+ wordlen = len(input1)
+ words = []
+ for d in dicts:
+ if len(d) == wordlen:
+ words.append(d)
+
+ A = [[input1]]
+ B = [[input2]]
+
+ center = []
+ lvl = 0
+ while lvl < limit and not center:
+ anew = []; bnew = []
+ for wa in A[lvl]:
+ for w in expand(wa, words):
+ anew.append(w)
+ for wb in B[lvl]:
+ for w in expand(wb, words):
+ bnew.append(w)
+
+ uniq_a = []
+ uniq_b = []
+ for item in anew:
+ if item not in uniq_a:
+ uniq_a.append(item)
+ for item in bnew:
+ if item not in uniq_b:
+ uniq_b.append(item)
+
+ A.append(uniq_a)
+ B.append(uniq_b)
+ lvl += 1
+ center = check(lvl, lvl, A, B)
+ if lvl == limit:
+ return quit()
+ counter = lvl - 1
+ mylist = [center[0]]
+ x = neighbor(center[0], A[counter])
+ y = neighbor(center[0], B[counter])
+ if y is not None:
+ while counter > 0:
+ mylist = [x] + mylist
+ mylist.append(y)
+ counter -= 1
+ x = neighbor(x, A[counter])
+ y = neighbor(y, B[counter])
+
+ if x is not None:
+ mylist = [x] + mylist
+ if y is not None:
+ mylist.append(y)
+ print("Output:", mylist)
+
+l1 = ["pour", "cold", "peer", "knife", "prince"]
+l2 = ["made", "warm", "norm", "dance", "prance"]
+for i in range(len(l1)):
+ proc(l1[i], l2[i])
+
diff --git a/challenge-007/zapwai/rust/ch-1.rs b/challenge-007/zapwai/rust/ch-1.rs
new file mode 100644
index 0000000000..a7f31fe460
--- /dev/null
+++ b/challenge-007/zapwai/rust/ch-1.rs
@@ -0,0 +1,15 @@
+fn main() {
+ niven(51);
+}
+
+fn niven(n :i32) {
+ for i in 1 ..= n {
+ let mut num = i;
+ let mut tally = 0;
+ while num > 0 {
+ tally += num % 10;
+ num /= 10;
+ }
+ if i % tally == 0 {println!("{}", i);}
+ }
+}
diff --git a/challenge-007/zapwai/rust/ch-2.rs b/challenge-007/zapwai/rust/ch-2.rs
new file mode 100644
index 0000000000..d16cdc82cf
--- /dev/null
+++ b/challenge-007/zapwai/rust/ch-2.rs
@@ -0,0 +1,175 @@
+#![allow(non_snake_case)]
+use regex::Regex;
+
+fn main() {
+ let l1 : Vec<&str> = vec!["cold", "peer", "pour", "prince", "knife"];
+ let l2 : Vec<&str> = vec!["warm", "norm", "made", "prance", "dance"];
+ for i in 0 .. l1.len() {
+ proc(l1[i], l2[i]);
+ }
+}
+
+fn dist(word1 :String, word2 :String) -> i32 {
+ let mut cnt = 0;
+ for i in 0 .. word1.len() {
+ if &word1[i..i+1] != &word2[i..i+1] {
+ cnt += 1;
+ }
+ }
+ return cnt;
+}
+
+fn neighbor(word :&String, word_list :&Vec<String>) -> String {
+ for w in word_list {
+ if dist(w.clone(), word.clone()) == 1 {
+ return w.to_string();
+ }
+ }
+ return String::from("NULL");
+}
+
+fn check(m :usize, n :usize, A :&Vec<Vec<String>>, B :&Vec<Vec<String>>) -> Vec<String> {
+ let mut ans : Vec<String> = Vec::new();
+ for i in 0 ..= m {
+ for j in 0 ..= n {
+ let a = intersection(&A[i], &B[j]);
+ if a.len() > 0 {
+ for item in a {
+ ans.push(item);
+ }
+ }
+ }
+ }
+ return ans;
+}
+
+fn intersection(A :&Vec<String>, B :&Vec<String>) -> Vec<String> {
+ let mut list :Vec<String> = vec![];
+ for i in 0 .. A.len() {
+ for j in 0 .. B.len() {
+ if A[i] == B[j] {
+ list.push(A[i].clone());
+ }
+ }
+ }
+ return list;
+}
+
+fn read_file(filename :&str) -> Vec<String> {
+ return std::fs::read_to_string(filename)
+ .expect("No file?")
+ .lines()
+ .map(|s| s.to_string())
+ .collect()
+}
+
+
+fn expand(word :&String, words :Vec<String>) -> Vec<String> {
+ let mut new : Vec<String>= Vec::new();
+ for i in 0 .. word.len() {
+ let pre = &word[0..i];
+ let post = &word[i+1..word.len()];
+ let a = format!(r"^{}.{}$", pre, post);
+ let re = Regex::new(&a).unwrap();
+ for w in &words {
+ if re.is_match(w) {
+ new.push(w.to_string());
+ }
+ }
+ }
+ let mut anew : Vec<String> = Vec::new();
+ for w in new {
+ if w != *word {
+ anew.push(w);
+ }
+ }
+ return anew;
+}
+
+fn proc(input1 :&str, input2 :&str) {
+ let filename = "src/bin/words";
+ let limit = 4; // max possible chain length is 2*limit
+
+ println!("Input: {} to {}", input1, input2);
+ let lines = read_file(filename);
+ let wordlen = input1.len();
+ if wordlen != input2.len() {
+ println!("Not the same lengths.");
+ return ();
+ }
+ let mut cnt = 0;
+ let a = format!(r"^{}$|^{}$",input1,input2);
+ let re = Regex::new(&a).unwrap();
+ for line in &lines {
+ if re.is_match(line) {
+ cnt += 1;
+ }
+ }
+ if cnt < 2 {
+ println!("One of these inputs is not considered a word.");
+ return ();
+ }
+ let words :Vec<String> = lines.into_iter().filter(|word| word.len() == wordlen).collect();
+ let mut A : Vec<Vec<String>> = vec![vec![input1.to_string()]];
+ let mut B : Vec<Vec<String>> = vec![vec![input2.to_string()]];
+ let mut center :Vec<String> = Vec::new();
+ let mut lvl = 0;
+ while lvl < limit && center.len() == 0 {
+ let mut anew :Vec<String> = Vec::new();
+ let mut bnew :Vec<String> = Vec::new();
+ for wa in &A[lvl] {
+ for w in expand(wa, words.clone()).iter() {
+ anew.push(w.to_string());
+ }
+ }
+ for wb in &B[lvl] {
+ for w in expand(wb, words.clone()).iter() {
+ bnew.push(w.to_string());
+ }
+ }
+
+ let mut uniq_a :Vec<String> = Vec::new();
+ let mut uniq_b :Vec<String> = Vec::new();
+
+ for w in anew {
+ if !uniq_a.iter().any(|i| *i == w) {
+ uniq_a.push(w);
+ }
+ }
+ for w in bnew {
+ if !uniq_b.iter().any(|i| *i == w) {
+ uniq_b.push(w);
+ }
+ }
+ A.push(uniq_a);
+ B.push(uniq_b);
+ lvl += 1;
+ center = check(lvl, lvl, &A, &B);
+ }
+ if lvl == limit {
+ println!("Output: ()");
+ return ();
+ }
+ let mut counter = lvl - 1;
+ let mut mylist = vec![center[0].clone()];
+ let mut x = neighbor(&center[0], &A[counter]);
+ let mut y = neighbor(&center[0], &B[counter]);
+ if y != "NULL" {
+ while counter > 0 {
+ let xtarget = x.c