aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYves Orton <demerphq@gmail.com>2023-10-15 18:15:40 +0200
committerYves Orton <demerphq@gmail.com>2023-10-15 18:16:57 +0200
commitf74b2e4890eb1fff7aa03c2685fdab6668b89226 (patch)
tree617d366e471342e1412b28a34aba672c4db95987
parentd9345ca8d5bd2ffac181bec0e44d891769273c9d (diff)
downloadperlweeklychallenge-club-f74b2e4890eb1fff7aa03c2685fdab6668b89226.tar.gz
perlweeklychallenge-club-f74b2e4890eb1fff7aa03c2685fdab6668b89226.tar.bz2
perlweeklychallenge-club-f74b2e4890eb1fff7aa03c2685fdab6668b89226.zip
Challenge 238, Perl, Rust, JS, and C
-rwxr-xr-xchallenge-238/demerphq/C/build_and_test.sh7
-rw-r--r--challenge-238/demerphq/C/ch-1.c66
-rw-r--r--challenge-238/demerphq/C/ch-2.c133
-rw-r--r--challenge-238/demerphq/README.md139
-rw-r--r--challenge-238/demerphq/js/ch-1.js26
-rw-r--r--challenge-238/demerphq/js/ch-2.js57
-rw-r--r--challenge-238/demerphq/perl/ch-1.pl26
-rw-r--r--challenge-238/demerphq/perl/ch-2.pl41
-rw-r--r--challenge-238/demerphq/rust/Cargo.lock16
-rw-r--r--challenge-238/demerphq/rust/Cargo.toml17
-rw-r--r--challenge-238/demerphq/rust/src/ch-1.rs48
-rw-r--r--challenge-238/demerphq/rust/src/ch-2.rs92
-rw-r--r--challenge-238/demerphq/rust/src/main.rs3
13 files changed, 532 insertions, 139 deletions
diff --git a/challenge-238/demerphq/C/build_and_test.sh b/challenge-238/demerphq/C/build_and_test.sh
new file mode 100755
index 0000000000..35a1fc97eb
--- /dev/null
+++ b/challenge-238/demerphq/C/build_and_test.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/bash
+gcc -o ch-1 ch-1.c
+gcc -o ch-2 ch-2.c
+echo === ch-1 ==========================================
+./ch-1
+echo === ch-2 ==========================================
+./ch-2
diff --git a/challenge-238/demerphq/C/ch-1.c b/challenge-238/demerphq/C/ch-1.c
new file mode 100644
index 0000000000..87bc8c0857
--- /dev/null
+++ b/challenge-238/demerphq/C/ch-1.c
@@ -0,0 +1,66 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#define ARRAY_LENGTH(arr) (sizeof(arr) / sizeof((arr)[0]))
+#define ARRAY(...) __VA_ARGS__
+#define STMT_START do
+#define STMT_END while (0)
+
+void
+print_int_array(char *prefix, int *array, size_t length) {
+ printf("%s ", prefix);
+ for (size_t i = 0; i < length; i++) {
+ if (i > 0) {
+ printf(", ");
+ }
+ printf("%d", array[i]);
+ }
+ printf("\n");
+}
+
+int *
+running_sum(int *array, size_t length) {
+ int* sum = (int *)malloc(length * sizeof(int));
+ if (!sum) {
+ perror("Memory allocation failed");
+ exit(1);
+ }
+ sum[0] = array[0];
+ for (size_t i = 1; i < length; i++) {
+ sum[i] = array[i] + sum[i - 1];
+ }
+ return sum;
+}
+
+
+#define TEST_RUNNING_SUM(a1,a2) STMT_START { \
+ int input[] = a1; \
+ int want[] = a2; \
+ int len = ARRAY_LENGTH(input); \
+ int *got = running_sum(input, len); \
+ assert(ARRAY_LENGTH(input) == ARRAY_LENGTH(want)); \
+ \
+ test_count++; \
+ print_int_array("# Input:", input, len); \
+ print_int_array("# R Sum:", got, len); \
+ print_int_array("# Want :", want, len); \
+ printf("%sok %d\n", memcmp(got, want, sizeof(want[0]) * len) \
+ ? "not " : "", test_count); \
+ free(got); \
+} STMT_END
+
+
+int
+run_tests() {
+ int test_count = 0;
+ TEST_RUNNING_SUM(ARRAY({1, 2, 3, 4, 5}), ARRAY({1, 3, 6, 10, 15}));
+ TEST_RUNNING_SUM(ARRAY({1, 1, 1, 1, 1}), ARRAY({1, 2, 3, 4, 5}));
+ TEST_RUNNING_SUM(ARRAY({0, -1, 1, 2}), ARRAY({0, -1, 0, 2}));
+}
+
+int
+main(int argc, char *argv[]) {
+ return run_tests();
+}
diff --git a/challenge-238/demerphq/C/ch-2.c b/challenge-238/demerphq/C/ch-2.c
new file mode 100644
index 0000000000..807f5b3890
--- /dev/null
+++ b/challenge-238/demerphq/C/ch-2.c
@@ -0,0 +1,133 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <assert.h>
+
+#define ARRAY_LENGTH(arr) (sizeof(arr) / sizeof((arr)[0]))
+#define ARRAY(...) __VA_ARGS__
+#define STMT_START do
+#define STMT_END while (0)
+
+void
+print_uint32_array(char *prefix, uint32_t *array, size_t length) {
+ printf("%s ", prefix);
+ for (size_t i = 0; i < length; i++) {
+ if (i > 0) {
+ printf(", ");
+ }
+ printf("%u", array[i]);
+ }
+ printf("\n");
+}
+
+
+// Function to calculate the digit weight of a number
+uint32_t digit_weight(uint32_t n) {
+ uint32_t count = 0;
+
+ while (n > 9) {
+ count++;
+ uint32_t tmp = 1;
+ uint32_t temp_n = n;
+
+ while (temp_n > 0) {
+ tmp *= temp_n % 10;
+ temp_n /= 10;
+ }
+
+ n = tmp;
+ }
+
+ return count;
+}
+
+struct sort_data {
+ uint32_t *weight;
+ uint32_t *data;
+};
+struct sort_data compare_state;
+
+int compare(const void *a, const void *b) {
+ const uint32_t l = *(uint32_t *)a;
+ const uint32_t r = *(uint32_t *)b;
+
+ if (compare_state.weight[l] == compare_state.weight[r]) {
+ if (compare_state.data[l] == compare_state.data[r]) {
+ return 0;
+ } else if (compare_state.data[l] < compare_state.data[r]) {
+ return -1;
+ } else {
+ return 1;
+ }
+ } else if (compare_state.weight[l] < compare_state.weight[r]) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
+
+// Function to sort the input array based on digit weight and value
+uint32_t *
+persistence_sort(uint32_t *array, uint32_t length) {
+ uint32_t bytes = length * sizeof(uint32_t);
+ uint32_t *weight = (uint32_t *)malloc(bytes);
+ uint32_t *sorted_idx = (uint32_t *)malloc(bytes);
+
+ for (uint32_t i = 0; i < length; i++) {
+ weight[i] = digit_weight(array[i]);
+ sorted_idx[i] = i;
+ }
+
+ compare_state.weight = weight;
+ compare_state.data = array;
+
+ // Sort the indices based on weight and value
+ qsort(sorted_idx, length, sizeof(uint32_t), compare);
+
+ for (uint32_t i = 0; i < length; i++) {
+ weight[i] = array[sorted_idx[i]];
+ }
+ free(sorted_idx);
+
+ return weight;
+}
+
+#define TEST_PERSISTENCE_SORT(a,b) STMT_START { \
+ uint32_t input[] = a; \
+ uint32_t want[] = b; \
+ int len = ARRAY_LENGTH(input); \
+ int *got = persistence_sort(input, len); \
+ assert(ARRAY_LENGTH(input) == ARRAY_LENGTH(want)); \
+ \
+ test_count++; \
+ print_uint32_array("# Input:", input, len); \
+ print_uint32_array("# Psort:", got, len); \
+ print_uint32_array("# Want :", want, len); \
+ printf("%sok %d\n", memcmp(got, want, sizeof(want[0]) * len) \
+ ? "not " : "", test_count); \
+ free(got); \
+} STMT_END
+
+
+int
+run_tests() {
+ uint32_t test_count = 0;
+
+ TEST_PERSISTENCE_SORT(ARRAY({15, 99, 1, 34}),
+ ARRAY({1, 15, 34, 99}));
+
+ TEST_PERSISTENCE_SORT(ARRAY({50, 25, 33, 22}),
+ ARRAY({22, 33, 50, 25}));
+
+ TEST_PERSISTENCE_SORT(ARRAY({12347, 2347, 347, 47, 7}),
+ ARRAY({ 7, 47, 347, 2347, 12347}));
+
+ return 0;
+}
+
+
+int
+main(int argc, char *argv[]) {
+ return run_tests();
+}
diff --git a/challenge-238/demerphq/README.md b/challenge-238/demerphq/README.md
deleted file mode 100644
index 66d2bdc1ca..0000000000
--- a/challenge-238/demerphq/README.md
+++ /dev/null
@@ -1,139 +0,0 @@
-# Challenge 237 - Seize The Day and Maximise Greatness
-
-## Seize The Day - Simple Rules The Day
-
-My solution was based on using Time::Local to compute the epoch for noon
-on the first day of the month, and then stepping forward by day until
-the required day of week has been found, and then stepping forward by
-week until the required repetition of that day has been found, or we ran
-off the end of the calender month. Using noon instead of midnight is IMO
-a prudent guard against issues related leap seconds, but probably isn't
-really necessary but doesn't hurt either.
-
-## Maximise Greatness - Permutation Misdirection
-
-Task #2 is more difficult and IMO more interesting. The problem is
-stated as the following: "Maximise Greatness: You are given an array of
-integers. Write a script to permute the give[n] array such that you get
-the maximum possible greatness. To determine greatness, [count pairs
-that satisfy] nums[i] < perm[i] where 0 <= i < nums.length", and then
-gives the example of
-
- Input: @nums = (1, 3, 5, 2, 1, 3, 1)
- Output: 4
-
- One possible permutation: (2, 5, 1, 3, 3, 1, 1)
- which returns 4 greatness as below:
- nums[0] < perm[0]
- nums[1] < perm[1]
- nums[3] < perm[3]
- nums[4] < perm[4]
-
-I think this is a fun little problem and a good example of the kind of
-problem that gets posed in the perl-weekly challenge. Simple input,
-simple output, simple description, but a deeper problem than it might
-seem at first blush.
-
-The reason I say deeper is that way the problem is stated it makes it
-seem like we need to compute a permutation, and that the solution to the
-problem might be `O(N!)` or `O(N**2)`. But on closer inspection we can
-see that we need not compute a permutation at all, and we only need to
-do so if we want to visually debug that our answer is correct. It
-actually turns out that all we need to do is find the count of the most
-frequently occuring number in the array. The maximum greatness will be
-the number of elements in the array minus the count of the most
-frequently occuring element in the array.
-
-A complete proof of this is a bit beyond this document. But we can get
-the general idea by considering a sorted array. Lets say we have an
-array with duplicates, such that `A[0] < A[1] < A[2] ... < A[n-1]`. It
-is obvious that the maximum element in the array is the only one that
-cannot be paired with something larger than it. We can view this as a
-rotation of the array:
-
-```
- | 1, 2, 3 |
- | 2, 3, 1 | <- rotate left by 1.
- | X X | <- Which columns satisfy the constraint
-```
-
-In this case it is obvious that the maximum greatness is 1 less than
-number of elements in the array, and 1 is the count of the most
-frequently occuring element. If we then duplicate one of the elements
-and we rotate the array by different numbers of elements we can see
-maximum is the same regardless of which element is duplicated, and that
-the rotating any more than the number of duplicates causes the number of
-pairs that satisify the constraint to reduce.
-
-```
- | 1, 1, 2, 3 | 1, 2, 2, 3 | 1, 2, 3, 3 |
- | 1, 2, 3, 1 | 2, 2, 3, 1 | 2, 3, 3, 1 | <- rotate 1
- | X X | X X | X X |
-
- | 1, 1, 2, 3 | 1, 2, 2, 3 | 1, 2, 3, 3 |
- | 2, 3, 1, 1 | 2, 3, 1, 2 | 3, 3, 1, 2 | <- rotate 2
- | X X | X X | X X |
-
- | 1, 1, 2, 3 | 1, 2, 2, 3 | 1, 2, 3, 3 |
- | 3, 1, 1, 2 | 3, 1, 2, 2 | 3, 1, 2, 3 | <- rotate 3
- | X | X | X |
-```
-
-The same pattern holds if the array contains two sets of duplicated
-numbers, the maximum number of pairs is found when the rotation matches
-the count of the most frequently repeated element:
-
-```
- | 1, 1, 2, 2, 3 | 1, 2, 2, 3, 3 | 1, 1, 2, 3, 3 |
- | 1, 2, 2, 3, 1 | 2, 2, 3, 3, 1 | 1, 2, 3, 3, 1 | <- rotate left by 1
- X X | X X | X X |
-
- | 1, 1, 2, 2, 3 | 1, 2, 2, 3, 3 | 1, 1, 2, 3, 3 |
- | 2, 2, 3, 1, 1 | 2, 3, 3, 1, 2 | 2, 3, 3, 1, 1 | <- rotate left by 2
- | X X X | X X X | X X X |
-
- | 1, 1, 2, 2, 3 | 1, 2, 2, 3, 3 | 1, 1, 2, 3, 3 |
- | 2, 3, 1, 1, 2 | 3, 3, 1, 2, 2 | 3, 3, 1, 1, 2 | <- rotate left by 3
- | X X | X X | X X |
-```
-
-And lastly consider what happens when we have 1 unique element, 1 pair,
-and 1 triplicate:
-
-```
- | 1, 2, 2, 3, 3, 3 | 1, 1, 2, 2, 2, 3 | 1, 1, 1, 2, 3, 3 |
- | 2, 2, 3, 3, 3, 1 | 1, 2, 2, 2, 3, 1 | 1, 1, 2, 3, 3, 1 | <- rotate 1
- | X X | X X | X X |
-
- | 1, 2, 2, 3, 3, 3 | 1, 1, 2, 2, 2, 3 | 1, 1, 1, 2, 3, 3 |
- | 2, 3, 3, 3, 1, 2 | 2, 2, 2, 3, 1, 1 | 1, 2, 3, 3, 1, 1 | <- rotate 2
- | X X X | X X X | X X X |
-
- | 1, 2, 2, 3, 3, 3 | 1, 1, 2, 2, 2, 3 | 1, 1, 1, 2, 3, 3 |
- | 3, 3, 3, 1, 2, 2 | 2, 2, 3, 1, 1, 2 | 2, 3, 3, 1, 1, 1 | <- rotate 3
- | X X X | X X X | X X X |
-
- | 1, 2, 2, 3, 3, 3 | 1, 1, 2, 2, 2, 3 | 1, 1, 1, 2, 3, 3 |
- | 3, 3, 1, 2, 2, 3 | 2, 3, 1, 1, 2, 2 | 3, 3, 1, 1, 1, 2 | <- rotate 4
- | X X | X X | X X |
-```
-
-In each case we can see that the maximum greatness is determined only
-by the number of elements in the array and the count of the most
-frequent element. Note, that there may actually be two rotations of a
-sorted array that produce the maximum greatness, that of the count of
-the most frequent element, and that of the count of the second most
-frequent element. If the counts differ then there will be two possible
-rotations that give the maximum greatness.
-
-The last point to observe is that if we **must** produce a permutation
-that would produce the maximum greatness then we can produce an array
-`S` of the indexes of the input array such that `A[S[i]] <= A[S[i+1]]`.
-We can then solve for the sorted array by rotating it left by the count
-of the most frequent element, and then use `S` to map the solution into
-the appropriate order for the actual input array.
-
-Thus if we are to compute the maximum greatness alone we can do so
-in `O(N)` steps. If we are to produce a permutation of the input
-array would produce that maximum greatness we can do so in
-`O(N log2 N)` steps.
diff --git a/challenge-238/demerphq/js/ch-1.js b/challenge-238/demerphq/js/ch-1.js
new file mode 100644
index 0000000000..6e7a6f78c6
--- /dev/null
+++ b/challenge-238/demerphq/js/ch-1.js
@@ -0,0 +1,26 @@
+"use strict";
+
+function runningSum(array) {
+ const sum = [];
+ sum[0] = array[0];
+ for (let i = 1; i < array.length; i++) {
+ sum[i] = array[i] + sum[i - 1];
+ }
+ return sum;
+}
+
+const assert = require('assert');
+
+const testCases = [
+ { input: [1, 2, 3, 4, 5], want: [1, 3, 6, 10, 15] },
+ { input: [1, 1, 1, 1, 1], want: [1, 2, 3, 4, 5] },
+ { input: [0, -1, 1, 2], want: [0, -1, 0, 2] },
+];
+
+testCases.forEach((testCase, index) => {
+ const { input, want } = testCase;
+ const got = runningSum(input);
+ assert.deepStrictEqual(got, want, `Test [${input}]`);
+});
+
+console.log('All tests passed.');
diff --git a/challenge-238/demerphq/js/ch-2.js b/challenge-238/demerphq/js/ch-2.js
new file mode 100644
index 0000000000..6c69e3587e
--- /dev/null
+++ b/challenge-238/demerphq/js/ch-2.js
@@ -0,0 +1,57 @@
+"use strict"; // make the browsers happy.
+
+const digitWeight = {};
+
+function calculateDigitWeight(num) {
+ if (digitWeight[num] !== undefined) {
+ return digitWeight[num];
+ }
+
+ if (num < 0) {
+ throw new Error(`Not expecting a negative number (${num})`);
+ }
+
+ let n = num;
+ let count = 0;
+
+ while (n > 9) {
+ count++;
+ const digits = n.toString().split('').map(Number);
+ n = digits.pop();
+ while (digits.length > 0) {
+ n *= digits.pop();
+ }
+ }
+
+ digitWeight[num] = count;
+ return count;
+}
+
+function persistenceSort(array) {
+ return array.sort((a, b) => {
+ const weightA = calculateDigitWeight(a);
+ const weightB = calculateDigitWeight(b);
+
+ if (weightA !== weightB) {
+ return weightA - weightB;
+ } else {
+ return a - b;
+ }
+ });
+}
+
+const assert = require('assert');
+
+const testCases = [
+ { input: [15, 99, 1, 34], want: [1, 15, 34, 99] },
+ { input: [50, 25, 33, 22], want: [22, 33, 50, 25] },
+ { input: [12347, 2347, 347, 47, 7], want: [7, 47, 347, 2347, 12347] },
+];
+
+testCases.forEach((testCase) => {
+ const { input, want } = testCase;
+ const output = persistenceSort([...input]);
+ assert.deepStrictEqual(output, want, `persistenceSort(${input})`);
+});
+
+console.log('All tests passed.');
diff --git a/challenge-238/demerphq/perl/ch-1.pl b/challenge-238/demerphq/perl/ch-1.pl
new file mode 100644
index 0000000000..e5313febeb
--- /dev/null
+++ b/challenge-238/demerphq/perl/ch-1.pl
@@ -0,0 +1,26 @@
+use strict;
+use warnings;
+
+sub running_sum {
+ my ($array) = @_;
+ my @sum;
+ $sum[0] = $array->[0];
+ for(my $i = 1; $i < @$array; $i++) {
+ $sum[$i] = $array->[$i] + $sum[$i-1];
+ }
+ return \@sum;
+}
+
+use Test::More;
+
+foreach my $tuple (
+ [[1, 2, 3, 4, 5], [1, 3, 6, 10, 15]],
+ [[1, 1, 1, 1, 1], [1, 2, 3, 4, 5]],
+ [[0, -1, 1, 2], [0, -1, 0, 2]],
+) {
+ my ($input, $want) = @$tuple;
+ my $got = running_sum($input);
+ is( "@$got", "@$want", "Test [@$input]");
+}
+done_testing();
+__END__
diff --git a/challenge-238/demerphq/perl/ch-2.pl b/challenge-238/demerphq/perl/ch-2.pl
new file mode 100644
index 0000000000..f875bebd87
--- /dev/null
+++ b/challenge-238/demerphq/perl/ch-2.pl
@@ -0,0 +1,41 @@
+use strict;
+use warnings;
+
+my %digit_weight;
+sub digit_weight {
+ my ($num)= @_;
+
+ return $digit_weight{$num} //= do {
+ die "Not expecting a negative number ($num)" if $num < 0;
+ my $n = $num;
+ my $count = 0;
+
+ while ($n > 9) {
+ $count++;
+ my $tmp = 1;
+ for my $digit (split //, $n) {
+ $tmp *= $digit;
+ }
+ $n = $tmp;
+ }
+ $count;
+ };
+}
+
+sub persistence_sort {
+ my ($array) = @_;
+ my @sorted= sort { digit_weight($a) <=> digit_weight($b) || $a <=> $b } @$array;
+ return \@sorted;
+}
+
+use Test::More;
+foreach my $tuple (
+ [ [ 15, 99, 1, 34], [ 1, 15, 34, 99 ] ],
+ [ [ 50, 25, 33, 22], [ 22, 33, 50, 25 ] ],
+ [ [ 12347, 2347, 347, 47, 7], [ 7, 47, 347, 2347, 12347 ] ],
+) {
+ my ($input, $want) = @$tuple;
+ my $output = persistence_sort($input);
+ is("@$output","@$want","persistence_sort(@$input)");
+}
+done_testing();
diff --git a/challenge-238/demerphq/rust/Cargo.lock b/challenge-238/demerphq/rust/Cargo.lock
new file mode 100644
index 0000000000..2a398e9b28
--- /dev/null
+++ b/challenge-238/demerphq/rust/Cargo.lock
@@ -0,0 +1,16 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "challenge-238"
+version = "0.1.0"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
diff --git a/challenge-238/demerphq/rust/Cargo.toml b/challenge-238/demerphq/rust/Cargo.toml
new file mode 100644
index 0000000000..a8451f6d2e
--- /dev/null
+++ b/challenge-238/demerphq/rust/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "challenge-238"
+version = "0.1.0"
+edition = "2021"
+
+[[bin]]
+name = "ch-1"
+path = "src/ch-1.rs"
+
+[[bin]]
+name = "ch-2"
+path = "src/ch-2.rs"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+once_cell = "1.7"
diff --git a/challenge-238/demerphq/rust/src/ch-1.rs b/challenge-238/demerphq/rust/src/ch-1.rs
new file mode 100644
index 0000000000..56aaabc5d2
--- /dev/null
+++ b/challenge-238/demerphq/rust/src/ch-1.rs
@@ -0,0 +1,48 @@
+use std::env;
+
+fn running_sum(array: &Vec<i32>) -> Vec<i32> {
+ let mut sum = Vec::new();
+ sum.push(array[0]);
+
+ for i in 1..array.len() {
+ sum.push(array[i] + sum[i - 1]);
+ }
+
+ sum
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_running_sum() {
+ let test_cases = vec![
+ (vec![1, 2, 3, 4, 5], vec![1, 3, 6, 10, 15]),
+ (vec![1, 1, 1, 1, 1], vec![1, 2, 3, 4, 5]),
+ (vec![0, -1, 1, 2], vec![0, -1, 0, 2]),
+ ];
+
+ for (input, want) in test_cases {
+ let got = running_sum(&input);
+ assert_eq!(got, want);
+ }
+ }
+}
+
+fn main() {
+ // Get command-line arguments, excluding the program name
+ let args: Vec<String> = env::args().collect();
+
+ // Create a Vec<i32> by parsing the command-line arguments
+ let in_vec: Vec<i32> = args
+ .iter()
+ .skip(1) // Skip the first argument, which is the program name
+ .filter_map(|arg| arg.parse().ok())
+ .collect();
+
+ // Print the resulting Vec<i32>
+ let out_vec: Vec<i32> = running_sum(&in_vec);
+ println!(" Input: {:?}", in_vec);
+ println!("Running Sum: {:?}", out_vec);
+}
diff --git a/challenge-238/demerphq/rust/src/ch-2.rs b/challenge-238/demerphq/rust/src/ch-2.rs
new file mode 100644
index 0000000000..7d270460d0
--- /dev/null
+++ b/challenge-238/demerphq/rust/src/ch-2.rs
@@ -0,0 +1,92 @@
+use std::collections::HashMap;
+use once_cell::sync::Lazy;
+use std::sync::Mutex;
+use std::env;
+
+static DIGIT_WEIGHT: Lazy<Mutex<HashMap<i32, i32>>> = Lazy::new(|| {
+ Mutex::new(HashMap::new())
+});
+
+fn calculate_digit_weight(num: i32) -> i32 {
+ let mut cache = DIGIT_WEIGHT.lock().unwrap();
+
+ if let Some(&cached) = cache.get(&num) {
+ return cached;
+ }
+
+ let mut n = num;
+ let mut count = 0;
+
+ while n > 9 {
+ count += 1;
+ let mut tmp = 1;
+ for digit in n.to_string().chars() {
+ tmp *= digit.to_digit(10).unwrap() as i32;
+ }
+ n = tmp;
+ }
+
+ cache.insert(num, count);
+ count
+}
+
+fn persistence_sort(array: &Vec<i32>) -> Vec<i32> {
+ let mut sorted_array = array.clone();
+
+ sorted_array.sort_by(|a, b| {
+ let weight_a = calculate_digit_weight(*a);
+ let weight_b = calculate_digit_weight(*b);
+
+ if weight_a != weight_b {
+ weight_a.cmp(&weight_b)
+ } else {
+ a.cmp(b)
+ }
+ });
+
+ sorted_array
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_calculate_digit_weight() {
+ assert_eq!(calculate_digit_weight(9), 0);
+ assert_eq!(calculate_digit_weight(15), 1);
+ assert_eq!(calculate_digit_weight(99), 2);
+ assert_eq!(calculate_digit_weight(12347), 4);
+ }
+
+ #[test]
+ fn test_persistence_sort() {
+ let test_cases = vec![
+ (vec![15, 99, 1, 34], vec![1, 15, 34, 99]),
+ (vec![50, 25, 33, 22], vec![22, 33, 50, 25]),
+ (vec![12347, 2347, 347, 47, 7], vec![7, 47, 347, 2347, 12347]),
+ ];
+
+ for (input, want) in test_cases {
+ let output = persistence_sort(&input);
+ assert_eq!(output, want);
+ }
+ }
+}
+
+fn main() {
+ // Get command-line arguments, excluding the program name
+ let args: Vec<String> = env::args().collect();
+
+ // Create a Vec<i32> by parsing the command-line arguments
+ let in_vec: Vec<i32> = args
+ .iter()
+ .skip(1) // Skip the first argument, which is the program name
+ .filter_map(|arg| arg.parse().ok())
+ .collect();
+
+ // Print the resulting Vec<i32>
+ let out_vec: Vec<i32> = persistence_sort(&in_vec);
+ println!(" Input: {:?}", in_vec);
+ println!("Running Sum: {:?}", out_vec);
+}
diff --git a/challenge-238/demerphq/rust/src/main.rs b/challenge-238/demerphq/rust/src/main.rs
new file mode 100644
index 0000000000..54b1a5b863
--- /dev/null
+++ b/challenge-238/demerphq/rust/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("use `cargo test` to run tests");
+}