aboutsummaryrefslogtreecommitdiff
path: root/challenge-133
diff options
context:
space:
mode:
authorIan Goodnight <goodnight.ian@gmail.com>2021-10-09 14:55:44 -0400
committerIan Goodnight <goodnight.ian@gmail.com>2021-10-09 14:55:44 -0400
commitc0428c3468203840d5cd0948d298fa86a72f1c9c (patch)
treec1b13cc2490ebf075763b5730b97f752a945445e /challenge-133
parent7e31b242f4012d100b2949c29f00a3597a9bb80f (diff)
downloadperlweeklychallenge-club-c0428c3468203840d5cd0948d298fa86a72f1c9c.tar.gz
perlweeklychallenge-club-c0428c3468203840d5cd0948d298fa86a72f1c9c.tar.bz2
perlweeklychallenge-club-c0428c3468203840d5cd0948d298fa86a72f1c9c.zip
solutions 133
Diffstat (limited to 'challenge-133')
-rw-r--r--challenge-133/iangoodnight/javascript/README.md196
-rwxr-xr-xchallenge-133/iangoodnight/javascript/ch-1.js121
-rwxr-xr-xchallenge-133/iangoodnight/javascript/ch-2.js105
-rw-r--r--challenge-133/iangoodnight/perl/README.md233
-rwxr-xr-xchallenge-133/iangoodnight/perl/ch-1.pl140
-rwxr-xr-xchallenge-133/iangoodnight/perl/ch-2.pl143
-rw-r--r--challenge-133/iangoodnight/ruby/README.md146
-rwxr-xr-xchallenge-133/iangoodnight/ruby/ch-1.rb79
-rwxr-xr-xchallenge-133/iangoodnight/ruby/ch-2.rb81
9 files changed, 1244 insertions, 0 deletions
diff --git a/challenge-133/iangoodnight/javascript/README.md b/challenge-133/iangoodnight/javascript/README.md
new file mode 100644
index 0000000000..6091157137
--- /dev/null
+++ b/challenge-133/iangoodnight/javascript/README.md
@@ -0,0 +1,196 @@
+# [Perl Weekly Challenge - 133] _JavaScript Edition_
+
+
+**Trigger warning:** There's lots of math in this week's challenges. Recovering
+math addicts may want to avoid these solutions. Personally, I've always been
+more the "hooked on phonics" type, so it was fun brushing up on some of these
+mathematical concepts as I worked through my solutions.
+
+## Task 1 > Integer Square Root
+
+You are given a positive integer `$N`.
+
+Write a script to calculate the integer square root of the given number.
+
+Please avoid using built-in function. Find out more about it [here].
+
+**Examples**
+
+```
+Input: $N = 10
+Output: 3
+
+Input: $N = 27
+Output: 5
+
+Input: $N = 85
+Output: 9
+
+Input: $N = 101
+Output: 10
+```
+
+### Solution
+
+I wasn't familiar with the idea of integer square roots, but after checking out
+the linked Wikipedia reference ([here]), I found that the term is equivalent to
+the largest integer square root that is less than or equal to our given input
+(a square root floor, so to speak. There are likely more elegant, mathematical
+approaches to this problem, but my approach was to just start at 0 and check
+incrementing squares until I exceeded the input.
+
+```javascript
+
+function returnIntSqrRoot(input) {
+ // Validate input
+ if (!Number.isInteger(+input) || +input < 0) {
+ throw new Error(
+ 'returnIntSqrRoot expects a positive integer as an argument',
+ );
+ }
+ // Crawl through squares starting with 0
+ let i = 0;
+ while (i * i <= +input) {
+ i += 1;
+ }
+ // return the highest passing number
+ i -= 1;
+ return i;
+}
+
+```
+
+#### `ch-1.js`
+
+Generally, I try to write a little test runner and some test cases, but in this
+case, it felt like overkill, so instead running `./ch-1.pl` initiates a mini
+REPL. Writing a REPL with Node is a lot of fun. Instead of the perlish
+`while (<>)` style of handling user input, Node's `readline` is event-driven.
+The REPL prompts for input and returns the integer square root. Sample output
+is shown below:
+
+```
+$> ./ch-1.js
+
+==============================
+Integer Square Root Calculator
+==============================
+
+Enter a positive integer (or, type "exit" to quit)> 10
+Integer square root: 3
+Try again? (y/n)> y
+Enter a positive integer (or, type "exit" to quit)> 27
+Integer square root: 5
+Try again? (y/n)> y
+Enter a positive integer (or, type "exit" to quit)> 85
+Integer square root: 9
+Try again? (y/n)> y
+Enter a positive integer (or, type "exit" to quit)> 101
+Integer square root: 10
+Try again? (y/n)> n
+Goodbye.
+
+```
+
+## Task 2 > Smith Number
+
+Write a script to generate the first 10 `Smith Numbers` in base 10.
+
+According to Wikipedia:
+
+> In number theory, a Smith number is a composite number for which, in a given
+> number base, the sum of its digits is equal to the sum of the digits in its
+> prime factorization in the given number base.
+
+### Solution
+
+At first, the language of this challenge had me feeling a little out of my
+depths. But, breaking down the problem, I realized that it wasn't as
+complicated as I had initially believed. It was clear that I needed a
+subroutine to reduce a given number to its prime factors, a subroutine to
+reduce a number to the sum of its digits, and that between those two functions,
+I could find these "Smith Numbers." Admittedly, my first solutions were all
+incorrect as I glazed right over that phrase "composite number," which, I've
+since learned, is a fancy way of saying "ain't prime."
+
+```javascript
+
+// First, we need a utility function to return our prime factors
+function primeFactors(number) {
+ let n = parseInt(number, 10); // Input validation
+ if (number === 'NaN') {
+ // Fail fast if arg is not a positive integer
+ throw new Error(
+ 'function `primeFactors` expects a positive integer as an argument.',
+ );
+ }
+ const factors = [];
+
+ let divisor = 2; // Starting with 2, check for remainder
+ while (n >= 2) {
+ if (n % divisor === 0) {
+ // If modulo is 0, push to factors
+ factors.push(divisor);
+ n /= divisor;
+ } else {
+ divisor += 1; // Else, increment the divisor and try again
+ }
+ }
+ return factors;
+}
+
+// Reduce numbers to the sum of their digits
+function sumDigits(number) {
+ return number
+ .toString()
+ .split('')
+ .reduce((sum, digit) => sum + parseInt(digit, 10), 0);
+}
+
+// Find our actual smith numbers with the help of `primeFactors` and `sumDigits`
+function identifySmithNumbers(limit = 10) {
+ const smithNumbers = [];
+
+ let test = 4; // Smith numbers are composite numbers, so skip the primes
+ while (smithNumbers.length < limit) {
+ const primeFactorsArr = primeFactors(test);
+
+ const factorSum = primeFactorsArr.reduce(
+ (sum, factor) => sum + sumDigits(factor),
+ 0,
+ );
+
+ const digitSum = sumDigits(test);
+
+ if (factorSum === digitSum && primeFactorsArr.length !== 1) {
+ smithNumbers.push(test);
+ }
+ test += 1;
+ }
+ return smithNumbers;
+}
+
+```
+
+### `ch-2.js`
+
+Again, this didn't feel like a situation for writing a bunch of tests, as I
+wasn't sure the solution even worked until I compared the output against a list
+of `Smith Numbers` I found online, so running `./ch-2.js` will output the first
+10 `Smith Numbers` without much in the way of pomp or circumstance. Optionally,
+you can run `./ch-2.js` with a number argument to display more or less `Smith
+Numbers` (i.e., `./ch-2.js 100` to return the first 100 `Smith Numbers`).
+Sample output is shown below:
+
+```
+$> ./ch-2.js 10
+The first 10 Smith Numbers are 4, 22, 27, 58, 85, 94, 121, 166, 202, and 265.
+```
+
+## Closing
+
+I had a lot of fun with these challenges and picked up a little bit of math that
+I might have otherwise avoided like the plague. Thanks again, PWC.
+
+[Perl Weekly Challenge - 133]: https://theweeklychallenge.org/blog/perl-weekly-challenge-133/
+[here]: https://en.wikipedia.org/wiki/Integer_square_root
diff --git a/challenge-133/iangoodnight/javascript/ch-1.js b/challenge-133/iangoodnight/javascript/ch-1.js
new file mode 100755
index 0000000000..c136092774
--- /dev/null
+++ b/challenge-133/iangoodnight/javascript/ch-1.js
@@ -0,0 +1,121 @@
+#!/usr/bin/env node
+// ch-1.js
+
+/**
+ * https://theweeklychallenge.org/blog/perl-weekly-challenge-133/
+ *
+ * Task 1 > Integer Square Root
+ * ============================
+ *
+ * You are given a positive integer `$N`.
+ *
+ * Write a script to calculate the integer square root of the given number.
+ *
+ * Please avoid using built-in function. Find out more about it here
+ * (https://en.wikipedia.org/wiki/Integer_square_root).
+ *
+ * Examples
+ * --------
+ *
+ * Input: $N = 10
+ * Output: 3
+ *
+ * Input: $N = 27
+ * Output: 5
+ *
+ * Input: $N = 85
+ * Output: 9
+ *
+ * Input: $N = 101
+ * Output: 10
+ *
+ **/
+
+'use strict';
+
+/**
+ * Node built-in dependencies
+ **/
+
+const readline = require('readline');
+
+/**
+ * Our PWC solution
+ **/
+
+function returnIntSqrRoot(input) {
+ // Validate input
+ if (!Number.isInteger(+input) || +input < 0) {
+ throw new Error(
+ 'returnIntSqrRoot expects a positive integer as an argument',
+ );
+ }
+ // Crawl through squares starting with 0
+ let i = 0;
+ while (i * i <= +input) {
+ i += 1;
+ }
+ // return the highest passing number
+ i -= 1;
+ return i;
+}
+
+/**
+ * Utilities
+ **/
+
+function repl() {
+ return new Promise((resolve) => {
+ const rl = readline.createInterface({
+ input: process.stdin,
+ output: process.stdout,
+ });
+ rl.setPrompt(
+ 'Enter a positive integer (or, type "\x1b[33mexit\x1b[0m" to quit)> ',
+ );
+ rl.prompt();
+ rl.on('line', (line) => {
+ const trimmed = line.trim();
+
+ if (trimmed === 'exit' || trimmed === 'n') {
+ return rl.close();
+ }
+ if (trimmed === 'y') return rl.prompt();
+ if (Number.isInteger(+trimmed)) {
+ console.log('Integer square root:', returnIntSqrRoot(+trimmed));
+ } else {
+ console.log('Arguments must be positive integers only.');
+ }
+ return process.stdout.write(
+ 'Try again? (\x1b[33my\x1b[0m/\x1b[33mn\x1b[0m)> ',
+ );
+ }).on('close', () => {
+ console.log('Goodbye.');
+ resolve();
+ });
+ });
+}
+
+function printBanner() {
+ const message = 'Integer Square Root Calculator';
+
+ const outline = '='.repeat(message.length);
+
+ const fgCyan = '\x1b[36m';
+
+ const reset = '\x1b[0m';
+
+ const banner = `\n${outline}\n${message}\n${outline}\n`;
+
+ console.log(fgCyan + banner + reset);
+}
+
+(async function main() {
+ try {
+ printBanner();
+ await repl();
+ } catch (error) {
+ console.log(error);
+ process.exit(1);
+ }
+})();
diff --git a/challenge-133/iangoodnight/javascript/ch-2.js b/challenge-133/iangoodnight/javascript/ch-2.js
new file mode 100755
index 0000000000..5f229008ec
--- /dev/null
+++ b/challenge-133/iangoodnight/javascript/ch-2.js
@@ -0,0 +1,105 @@
+#!/usr/bin/env node
+// ch-2.js
+
+/**
+ * https://theweeklychallenge.org/blog/perl-weekly-challenge-133/
+ *
+ * Task 2 > Smith Numbers
+ * ======================
+ *
+ * Write a script to generate the first 10 `Smith Numbers` in base 10.
+ *
+ * According to Wikipedia:
+ *
+ * > In number theory, a Smith number is a composite number for which, in a
+ * > given number base, the sum of its digits is equal to the sum of the digits
+ * > in its prime factorization in the given number base.
+ *
+ **/
+
+'use strict';
+
+/**
+ * Our PWC solution and some helper functions
+ **/
+
+// First, we need a utility function to return our prime factors
+function primeFactors(number) {
+ let n = parseInt(number, 10); // Input validation
+ if (number === 'NaN') {
+ // Fail fast if arg is not a positive integer
+ throw new Error(
+ 'function `primeFactors` expects a positive integer as an argument.',
+ );
+ }
+ const factors = [];
+
+ let divisor = 2; // Starting with 2, check for remainder
+ while (n >= 2) {
+ if (n % divisor === 0) {
+ // If modulo is 0, push to factors
+ factors.push(divisor);
+ n /= divisor;
+ } else {
+ divisor += 1; // Else, increment the divisor and try again
+ }
+ }
+ return factors;
+}
+
+// Reduce numbers to the sum of their digits
+function sumDigits(number) {
+ return number
+ .toString()
+ .split('')
+ .reduce((sum, digit) => sum + parseInt(digit, 10), 0);
+}
+
+// Find our actual smith numbers with the help of `primeFactors` and `sumDigits`
+function identifySmithNumbers(limit = 10) {
+ const smithNumbers = [];
+
+ let test = 4; // Smith numbers are composite numbers, so skip the primes
+ while (smithNumbers.length < limit) {
+ const primeFactorsArr = primeFactors(test);
+
+ const factorSum = primeFactorsArr.reduce(
+ (sum, factor) => sum + sumDigits(factor),
+ 0,
+ );
+
+ const digitSum = sumDigits(test);
+
+ if (factorSum === digitSum && primeFactorsArr.length !== 1) {
+ smithNumbers.push(test);
+ }
+ test += 1;
+ }
+ return smithNumbers;
+}
+
+/**
+ * General utilities
+ **/
+
+// Takes an array and returns it as human-readable comma separated list
+function stringWithOxfordComma(arr = []) {
+ const reversed = [...arr].reverse();
+
+ const [last, ...rest] = reversed;
+
+ const first = [...rest].reverse().join(', ');
+
+ return `${first}, and ${last}`;
+}
+
+// IIFE to handle args and print results
+(function main() {
+ const limit = process.argv[2] || 10;
+
+ const smithNumbers = identifySmithNumbers(limit);
+
+ const stringified = stringWithOxfordComma(smithNumbers);
+
+ console.log(`The first ${limit} Smith Numbers are ${stringified}.`);
+})();
diff --git a/challenge-133/iangoodnight/perl/README.md b/challenge-133/iangoodnight/perl/README.md
new file mode 100644
index 0000000000..a010ab26e6
--- /dev/null
+++ b/challenge-133/iangoodnight/perl/README.md
@@ -0,0 +1,233 @@
+# [Perl Weekly Challenge - 133]
+
+**Trigger warning:** There's lots of math in this week's challenges. Recovering
+math addicts may want to avoid these solutions. Personally, I've always been
+more the "hooked on phonics" type, so it was fun brushing up on some of these
+mathematical concepts as I worked through my solutions.
+
+## Task 1 > Integer Square Root
+
+You are given a positive integer `$N`.
+
+Write a script to calculate the integer square root of the given number.
+
+Please avoid using built-in function. Find out more about it [here].
+
+**Examples**
+
+```
+Input: $N = 10
+Output: 3
+
+Input: $N = 27
+Output: 5
+
+Input: $N = 85
+Output: 9
+
+Input: $N = 101
+Output: 10
+```
+
+### Solution
+
+I wasn't familiar with the idea of integer square roots, but after checking out
+the linked Wikipedia reference ([here]), I found that the term is equivalent to
+the largest integer square root that is less than or equal to our given input
+(a square root floor, so to speak. There are likely more elegant, mathematical
+approaches to this problem, but my approach was to just start at 0 and check
+incrementing squares until I exceeded the input.
+
+```perl
+
+sub return_int_sqr_root {
+ my $input = shift;
+ chomp $input;
+
+ # Validate input
+ $input =~ s{
+ ^\s+ # Leading whitespace
+ |
+ \s+$ # Trailing whitespace
+ }{}gmx;
+ if ( !$input =~ /^\d+$/m ) {
+ return;
+ }
+
+ # Crawl through squares starting with 0
+ my $i = 0;
+ while ( $i * $i <= $input ) {
+ $i++;
+ }
+
+ # Return the highest passing number
+ return --$i;
+}
+
+```
+
+#### `ch-1.pl`
+
+Generally, I try to write a little test runner and some test cases, but in this
+case, it felt like overkill, so instead running `./ch-1.pl` initiates a mini
+REPL. The REPL prompts for input and returns the integer square root. Sample
+output is shown below:
+
+```
+$> ./ch-1.pl
+
+==============================
+Integer Square Root Calculator
+==============================
+
+Enter a positive integer (or, type "exit" to quit)> 10
+Integer square root: 3
+Try again? (y/n)> y
+Enter a positive integer (or, type "exit" to quit)> 27
+Integer square root: 5
+Try again? (y/n)> y
+Enter a positive integer (or, type "exit" to quit)> 85
+Integer square root: 9
+Try again? (y/n)> y
+Enter a positive integer (or, type "exit" to quit)> 101
+Integer square root: 10
+Try again? (y/n)> n
+Goodbye.
+
+```
+
+## Task 2 > Smith Number
+
+Write a script to generate the first 10 `Smith Numbers` in base 10.
+
+According to Wikipedia:
+
+> In number theory, a Smith number is a composite number for which, in a given
+> number base, the sum of its digits is equal to the sum of the digits in its
+> prime factorization in the given number base.
+
+### Solution
+
+At first, the language of this challenge had me feeling a little out of my
+depths. But, breaking down the problem, I realized that it wasn't as
+complicated as I had initially believed. It was clear that I needed a
+subroutine to reduce a given number to its prime factors, a subroutine to
+reduce a number to the sum of its digits, and that between those two functions,
+I could find these "Smith Numbers." Admittedly, my first solutions were all
+incorrect as I glazed right over that phrase "composite number," which, I've
+since learned, is a fancy way of saying "ain't prime."
+
+```perl
+
+# First, we need a utility function to find and return our prime factors
+sub prime_factors {
+ my $number = shift;
+
+ $number =~ s{ # Trim whitespace, probably unnecessary, but it won't hurt
+ \A # Start of the line
+ \s+ # Leading whitespace
+ | # Alternating with
+ \s+ # Trailing whitespace
+ \z # End of line
+ }{}gx;
+
+ # Validate our input is an integer
+ if ( !$number =~ m/\A\d+\z/ ) {
+
+ # Bail
+ return 0;
+ }
+ my @factors;
+ my $divisor = 2; # Starting with 2, we'll divide and check for modulo
+
+ while ( $number >= 2 ) {
+ if ( $number % $divisor == 0 ) {
+
+ # If modulo is zero, push $divisor to @factors
+ push @factors, $divisor;
+ $number /= $divisor;
+ }
+ else {
+ # Else, increment $divisor and try again
+ $divisor += 1;
+ }
+ }
+ return \@factors;
+}
+
+# Helper to reduce number to sum of its digits
+sub sum_digits {
+ my $number = shift;
+
+ # Trim
+ $number =~ s{ \A \s+ | \s+ \z }{}gx;
+
+ # Split digits
+ my @digits = split //, $number;
+
+ # Reduce
+ my $sum = 0;
+ foreach my $digit (@digits) {
+ $sum += $digit;
+ }
+ return $sum;
+}
+
+# Find `Smith Numbers` with the help of our two subroutines, `prime_factors`
+# and `sum_digits`
+sub find_smith_numbers {
+
+ # We need to find the first ten, but we might as well write it to find more
+ my $limit = shift // '10';
+ my @smith_numbers;
+
+ # Smith Numbers are not prime numbers, so we might as well start at 4
+ my $test = '4';
+
+ # Search until we hit our limit
+ while ( scalar @smith_numbers < $limit ) {
+ my @primes = @{ prime_factors($test) };
+ my $factor_sum = 0;
+
+ # Reduce @primes to sum of its digits
+ foreach my $prime (@primes) {
+ $factor_sum += sum_digits($prime);
+ }
+
+ my $digit_sum = sum_digits($test);
+
+ # Check for matching sums and for prime number (if scalar @primes == 1,
+ # $test is a prime number)
+ if ( $factor_sum == $digit_sum && scalar @primes != 1 ) {
+ push @smith_numbers, $test;
+ }
+
+ $test += 1;
+ }
+ return \@smith_numbers;
+}
+
+```
+
+### `ch-2.pl`
+
+Again, this didn't feel like a situation for writing a bunch of tests, as I
+wasn't sure the solution even worked until I compared the output against a list
+of `Smith Numbers` I found online, so running `./ch-2.pl` will output the first
+10 `Smith Numbers` without much in the way of pomp or circumstance. Optionally,
+you can run `./ch-2.pl` with a number argument to display more or less `Smith
+Numbers` (i.e., `./ch-2.pl 100` to return the first 100 `Smith Numbers`).
+Sample output is shown below:
+
+```
+$> ./ch-2.pl 10
+The first 10 Smith Numbers are 4, 22, 27, 58, 85, 94, 121, 166, 202, and 265.
+```
+
+## Closing
+
+I had a lot of fun with these challenges and picked up a little bit of math that
+I might have otherwise avoided like the plague. Thanks again, PWC.
+
+[Perl Weekly Challenge - 133]: https://theweeklychallenge.org/blog/perl-weekly-challenge-133/
+[here]: https://en.wikipedia.org/wiki/Integer_square_root
diff --git a/challenge-133/iangoodnight/perl/ch-1.pl b/challenge-133/iangoodnight/perl/ch-1.pl
new file mode 100755
index 0000000000..4a2fa4e2fe
--- /dev/null
+++ b/challenge-133/iangoodnight/perl/ch-1.pl
@@ -0,0 +1,140 @@
+#!/usr/bin/perl
+# ch-1.pl
+
+=begin comment
+
+ * https://theweeklychallenge.org/blog/perl-weekly-challenge-133/
+ *
+ * Task 1 > Integer Square Root
+ * ============================
+ *
+ * You are given a positive integer `$N`.
+ *
+ * Write a script to calculate the integer square root of the given number.
+ *
+ * Please avoid using built-in function. Find out more about it here
+ * (https://en.wikipedia.org/wiki/Integer_square_root).
+ *
+ * Examples
+ * --------
+ *
+ * Input: $N = 10
+ * Output: 3
+ *
+ * Input: $N = 27
+ * Output: 5
+ *
+ * Input: $N = 85
+ * Output: 9
+ *
+ * Input: $N = 101
+ * Output: 10
+
+=end comment
+=cut
+
+use strict;
+use warnings;
+use utf8;
+use open ':std', ':encoding(UTF-8)';
+use Term::ANSIColor;
+
+################################################################################
+# Our PWC Solution
+################################################################################
+
+sub return_int_sqr_root {
+ my $input = shift;
+ chomp $input;
+
+ # Validate input
+ $input =~ s{
+ ^\s+ # Leading whitespace
+ |
+ \s+$ # Trailing whitespace
+ }{}gmx;
+ if ( !$input =~ /^\d+$/m ) {
+ return;
+ }
+
+ # Crawl through squares starting with 0
+ my $i = 0;
+ while ( $i * $i <= $input ) {
+ $i++;
+ }
+
+ # Return the highest passing number
+ return --$i;
+}
+
+################################################################################
+# Utilities
+################################################################################
+
+sub print_banner {
+ my $message = 'Integer Square Root Calculator';
+ my $border = q{=} x length $message;
+ my $empty = q{};
+ my @elements = ( $empty, $border, $message, $border, $empty, $empty );
+
+ return print color('cyan'), join( "\n", @elements ), color('reset');
+}
+
+################################################################################
+# REPL
+################################################################################
+
+sub main {
+ my $prompt =
+ 'Enter a positive integer (or, type "'
+ . color('yellow') . 'exit'
+ . color('reset')
+ . '" to quit)> ';
+
+ my $retry =
+ 'Try again? ('
+ . color('yellow') . 'y'
+ . color('reset') . q{/}
+ . color('yellow') . 'n'
+ . color('reset') . ')> ';
+
+ print_banner();
+ print $prompt;
+
+ my $complete = 0;
+
+ while ( my $line = <> ) {
+ chomp $line;
+ $line =~ s{
+ ^\s+ # Remove leading whitespace
+ |
+ \s+$ # Remove trailing whitespace
+ }{}gmx;
+
+ if ( $line eq 'exit' || $line eq 'n' ) {
+ print "Goodbye.\n";
+ return 1;
+ }
+ if ( $line eq 'y' ) {
+ $complete = 0;
+ print $prompt;
+ next;
+ }
+ if ( $line =~ m/^\d+$/m && !$complete ) {
+ print 'Integer square root: ';
+ print color('yellow'), return_int_sqr_root($line), color('reset'), "\n";
+ }
+ elsif ($complete) {
+ print "\n", $retry;
+ }
+ else {
+ print "Arguments must be positive integers only.\n";
+ }
+
+ $complete = 1;
+ print $retry;
+ }
+ return 1;
+}
+
+main();
diff --git a/challenge-133/iangoodnight/perl/ch-2.pl b/challenge-133/iangoodnight/perl/ch-2.pl
new file mode 100755
index 0000000000..0dfcdaf1c7
--- /dev/null
+++ b/challenge-133/iangoodnight/perl/ch-2.pl
@@ -0,0 +1,143 @@
+#!/usr/bin/perl
+# ch-2.pl
+
+=begin comment
+
+ * https://theweeklychallenge.org/blog/perl-weekly-challenge-133/
+ *
+ * Task 2 > Smith Numbers
+ * ======================
+ *
+ * Write a script to generate the first 10 `Smith Numbers` in base 10.
+ *
+ * According to Wikipedia:
+ *
+ * > In number theory, a Smith number is a composite number for which, in a
+ * > given number base, the sum of its digits is equal to the sum of the digits
+ * > in its prime factorization in the given number base.
+
+=end comment
+=cut
+
+use strict;
+use warnings;
+use utf8;
+use Data::Dumper;
+
+################################################################################
+# Our PWC solution, along with some help subroutines
+################################################################################
+
+# First, we need a utility function to find and return our prime factors
+sub prime_factors {
+ my $number = shift;
+
+ $number =~ s{ # Trim whitespace, probably unnecessary, but it won't hurt
+ \A # Start of the line
+ \s+ # Leading whitespace
+ | # Alternating with
+ \s+ # Trailing whitespace
+ \z # End of line
+ }{}gx;
+
+ # Validate our input is an integer
+ if ( !$number =~ m/\A\d+\z/ ) {
+
+ # Bail
+ return 0;
+ }
+ my @factors;
+ my $divisor = 2; # Starting with 2, we'll divide and check for modulo
+
+ while ( $number >= 2 ) {
+ if ( $number % $divisor == 0 ) {
+
+ # If modulo is zero, push $divisor to @factors
+ push @factors, $divisor;
+ $number /= $divisor;
+ }
+ else {
+ # Else, increment $divisor and try again
+ $divisor += 1;
+ }
+ }
+ return \@factors;
+}
+
+# Helper to reduce number to sum of its digits
+sub sum_digits {
+ my $number = shift;
+
+ # Trim
+ $number =~ s{ \A \s+ | \s+ \z }{}gx;
+
+ # Split digits
+ my @digits = split //, $number;
+
+ # Reduce
+ my $sum = 0;
+ foreach my $digit (@digits) {
+ $sum += $digit;
+ }
+ return $sum;
+}
+
+# Find `Smith Numbers` with the help of our two subroutines, `prime_factors`
+# and `sum_digits`
+sub find_smith_numbers {
+
+ # We need to find the first ten, but we might as well write it to find more
+ my $limit = shift // '10';
+ my @smith_numbers;
+
+ # Smith Numbers are not prime numbers, so we might as well start at 4
+ my $test = '4';
+
+ # Search until we hit our limit
+ while ( scalar @smith_numbers < $limit ) {
+ my @primes = @{ prime_factors($test) };
+ my $factor_sum = 0;
+
+ # Reduce @primes to sum of its digits
+ foreach my $prime (@primes) {
+ $factor_sum += sum_digits($prime);
+ }
+
+ my $digit_sum = sum_digits($test);
+
+ # Check for matching sums and for prime number (if scalar @primes == 1,
+ # $test is a prime number)
+ if ( $factor_sum == $digit_sum && scalar @primes != 1 ) {
+ push @smith_numbers, $test;
+ }
+
+ $test += 1;
+ }
+ return \@smith_numbers;
+}
+
+################################################################################
+# Utilities
+################################################################################
+
+sub list_with_oxford {
+ my @list = @{ +shift };
+ my $last_number = $list[-1];
+
+ return join( ', ', @list[ 0 .. $#list - 1 ] ) . ', and ' . $last_number;
+}
+
+################################################################################
+# Main
+################################################################################
+
+sub main {
+ my $limit = shift @ARGV // '10';
+ my $smith_numbers = find_smith_numbers $limit;
+ my $result_string = list_with_oxford $smith_numbers;
+
+ print "The first $limit Smith Numbers are $result_string.\n";
+ return 1;
+}
+
+main();
diff --git a/challenge-133/iangoodnight/ruby/README.md b/challenge-133/iangoodnight/ruby/README.md
new file mode 100644
index 0000000000..8854a2dfb4
--- /dev/null
+++ b/challenge-133/iangoodnight/ruby/README.md
@@ -0,0 +1,146 @@
+# [Perl Weekly Challenge - 133] _Ruby Edition_
+
+This is my first crack at a Ruby submission for the PWC. I'm still pretty new
+to the language, and porting my Perl to Ruby is a fun way to explore the syntax.
+
+## Task 1 > Integer Square Root
+
+You are given a positive integer `$N`.
+
+Write a script to calculate the integer square root of the given number.
+
+Please avoid using built-in function. Find out more about it [here].
+
+**Examples**
+
+```
+Input: $N = 10
+Output: 3
+
+Input: $N = 27
+Output: 5
+
+Input: $N = 85
+Output: 9
+
+Input: $N = 101
+Output: 10
+```
+
+### Solution
+
+This is pretty much a direct translation of my Perl solution, so it may be that
+I am missing some opportunities here.
+
+```ruby
+
+def int_sqr_root(input)
+ if !input.integer? || !input.positive?
+ puts 'Input must be a positive integer'
+ return
+ end
+ # Crawl through squares starting with 0
+ i = 0
+ (i += 1) while i * i <= input
+ # Return the highest passing number
+ i -= 1
+end
+
+```
+
+#### `ch-1.rb`
+
+Running `./ch-1.rb` initiates a mini REPL. The REPL prompts for input and
+returns the integer square root. Sample output is shown below:
+
+```
+$> ./ch-1.rb
+
+==============================
+Integer Square Root Calculator
+==============================
+
+Enter a positive integer (or, type "exit" to quit)> 10
+Integer square root: 3
+Try again? (y/n)> y
+Enter a positive integer (or, type "exit" to quit)> 27
+Integer square root: 5
+Try again? (y/n)> 85
+Integer square root: 9
+Try again? (y/n)> y
+Enter a positive integer (or, type "exit" to quit)> 101
+Integer square root: 10
+Try again? (y/n)> n
+Goodbye.
+
+```
+
+## Task 2 > Smith Number
+
+Write a script to generate the first 10 `Smith Numbers` in base 10.
+
+According to Wikipedia:
+
+> In number theory, a Smith number is a composite number for which, in a given
+> number base, the sum of its digits is equal to the sum of the digits in its
+> prime factorization in the given number base.
+
+### Solution
+
+```ruby
+
+# First, a utility method to find and return our prime factors
+def prime_factors(number)
+ factors = []
+ while number >= 2 # Starting with 2, divide and check modulo
+ if (number % divisor ||= 2).zero? # If modulo is zero, push to `factors`
+ factors.push(divisor)
+ number /= divisor
+ else
+ divisor += 1 # Else, increment divisor and try again
+ end
+ end
+ factors
+end
+
+# Helper method to reduce number to sum of it digits
+def sum_digits(number)
+ number.to_s.split(//).map(&:to_i).inject(0, :+)
+end
+
+# Method to reduce our primes to the sum of their digits
+def sum_primes(primes)
+ primes.reduce(0) { |sum, prime| sum + sum_digits(prime) }
+end
+
+# Find `Smith Numbers` with our methods, `prime_factors`, `sum_digits`,
+# `sum_primes`
+def find_smith_numbers(limit: 10)
+ smith_numbers = []
+ test = 4
+ while smith_numbers.length < limit.to_i
+ primes = prime_factors(test)
+ prime_sum = sum_primes(primes)
+ digit_sum = sum_digits(test)
+ smith_numbers.push(test) if pr