From 1146914ec3c881cc74db9101e2a6719e56f216d8 Mon Sep 17 00:00:00 2001 From: Loosetooth Date: Sun, 2 Feb 2025 22:08:01 +0100 Subject: [PATCH] add kata --- 5kyu/closest-and-smallest/description.md | 89 ++++++++++++++++++++++++ 5kyu/closest-and-smallest/solution.ts | 60 ++++++++++++++++ 5kyu/closest-and-smallest/tests.ts | 14 ++++ 3 files changed, 163 insertions(+) create mode 100644 5kyu/closest-and-smallest/description.md create mode 100644 5kyu/closest-and-smallest/solution.ts create mode 100644 5kyu/closest-and-smallest/tests.ts diff --git a/5kyu/closest-and-smallest/description.md b/5kyu/closest-and-smallest/description.md new file mode 100644 index 0000000..cb48fd9 --- /dev/null +++ b/5kyu/closest-and-smallest/description.md @@ -0,0 +1,89 @@ +Input +a string strng of n positive numbers (n = 0 or n >= 2) +Let us call weight of a number the sum of its digits. For example 99 will have "weight" 18, 100 will have "weight" 1. + +Two numbers are "close" if the difference of their weights is small. + +Task: +For each number in strng calculate its "weight" and then find two numbers of strng that have: + +the smallest difference of weights ie that are the closest +with the smallest weights +and with the smallest indices (or ranks, numbered from 0) in strng +Output: +an array of two arrays, each subarray in the following format: +[number-weight, index in strng of the corresponding number, original corresponding number in strng] + +or a pair of two subarrays (Haskell, Clojure, FSharp) or an array of tuples (Elixir, C++) + +or a (char*) in C or a string in some other languages mimicking an array of two subarrays or a string + +or a matrix in R (2 rows, 3 columns, no columns names) + +The two subarrays are sorted in ascending order by their number weights if these weights are different, by their indexes in the string if they have the same weights. + +Examples: +Let us call that function closest + +strng = "103 123 4444 99 2000" +the weights are 4, 6, 16, 18, 2 (ie 2, 4, 6, 16, 18) + +closest should return [[2, 4, 2000], [4, 0, 103]] (or ([2, 4, 2000], [4, 0, 103]) +or [{2, 4, 2000}, {4, 0, 103}] or ... depending on the language) +because 2000 and 103 have for weight 2 and 4, their indexes in strng are 4 and 0. +The smallest difference is 2. +4 (for 103) and 6 (for 123) have a difference of 2 too but they are not +the smallest ones with a difference of 2 between their weights. +.................... + +strng = "80 71 62 53" +All the weights are 8. +closest should return [[8, 0, 80], [8, 1, 71]] +71 and 62 have also: +- the smallest weights (which is 8 for all) +- the smallest difference of weights (which is 0 for all pairs) +- but not the smallest indices in strng. +.................... + +strng = "444 2000 445 544" +the weights are 12, 2, 13, 13 (ie 2, 12, 13, 13) + +closest should return [[13, 2, 445], [13, 3, 544]] or ([13, 2, 445], [13, 3, 544]) +or [{13, 2, 445}, {13, 3, 544}] or ... +444 and 2000 have the smallest weights (12 and 2) but not the smallest difference of weights; +they are not the closest. +Here the smallest difference is 0 and in the result the indexes are in ascending order. +................... + +closest("444 2000 445 644 2001 1002") --> [[3, 4, 2001], [3, 5, 1002]] or ([3, 4, 2001], +[3, 5, 1002]]) or [{3, 4, 2001}, {3, 5, 1002}] or ... +Here the smallest difference is 0 and in the result the indexes are in ascending order. +................... + +closest("239382 162 254765 182 485944 468751 49780 108 54") +The weights are: 27, 9, 29, 11, 34, 31, 28, 9, 9. +closest should return [[9, 1, 162], [9, 7, 108]] or ([9, 1, 162], [9, 7, 108]) +or [{9, 1, 162}, {9, 7, 108}] or ... +108 and 54 have the smallest difference of weights too, they also have +the smallest weights but they don't have the smallest ranks in the original string. +.................. + +closest("54 239382 162 254765 182 485944 468751 49780 108") +closest should return [[9, 0, 54], [9, 2, 162]] or ([9, 0, 54], [9, 2, 162]) +or [{9, 0, 54}, {9, 2, 162}] or ... +Notes : +If n == 0 closest("") should return [] + +or ([], []) in Haskell, Clojure, FSharp + +or [{}, {}] in Elixir or '(() ()) in Racket + +or {{0,0,0}, {0,0,0}} in C++ + +or "[(), ()]" in Go, Nim, + +or "{{0,0,0}, {0,0,0}}" in C, NULL in R + +or "" in Perl. + +See Example tests for the format of the results in your language. \ No newline at end of file diff --git a/5kyu/closest-and-smallest/solution.ts b/5kyu/closest-and-smallest/solution.ts new file mode 100644 index 0000000..b4ac269 --- /dev/null +++ b/5kyu/closest-and-smallest/solution.ts @@ -0,0 +1,60 @@ +const weight = (s: string): number => s.split('').reduce((acc, cur) => acc + parseInt(cur), 0); + +const sortWeightInfo = (a: T, b: T): number => { + if (a[0] !== b[0]) { + return a[0] - b[0]; + } else if (a[1] !== b[1]) { + return a[1] - b[1]; + } else { + return a[2] - b[2]; + } +} + +type WeightInfo = [ + number, // weight + number, // index + number // number +]; +type DiffInfo = [ + number, // weight difference + number, // weight sum + number, // index sum + number, // index of first number + number // index of second number +]; + +export function closest(strng: string): number[][] { + if (strng === '') return []; + + const weights: WeightInfo[] = strng + .split(' ') + .map((s, i) => [weight(s), i, parseInt(s)]); + + // calculate all weight differences, weight sum, and index sum + const diffs: DiffInfo[] = []; + for (const [weight, index, num] of weights) { + for (let i = index + 1; i < weights.length; i++) { + if(i >= weights.length) break; + + const [weight2, index2, num2] = weights[i]; + const weightDiff = Math.abs(weight - weight2); + const weightSum = weight + weight2; + const indexSum = index + index2; + diffs.push([weightDiff, weightSum, indexSum, index, index2]); + } + } + + // sort by weight difference, weight sum, and index sum + diffs.sort(sortWeightInfo); + + const minimumDiff = diffs[0] + const firstNumIndex = minimumDiff[3]; + const secondNumIndex = minimumDiff[4]; + + const result = [ + weights[firstNumIndex], + weights[secondNumIndex] + ].sort(sortWeightInfo) + + return result; +} \ No newline at end of file diff --git a/5kyu/closest-and-smallest/tests.ts b/5kyu/closest-and-smallest/tests.ts new file mode 100644 index 0000000..50f31a8 --- /dev/null +++ b/5kyu/closest-and-smallest/tests.ts @@ -0,0 +1,14 @@ +import { closest } from './solution'; +import { assert } from "chai"; +// chai.config.truncateThreshold = 0; + +describe("Fixed Tests", function() { + it("Basic tests closest", function() { + assert.deepEqual(closest(""), []); + assert.deepEqual(closest("103 123 4444 99 2000"), [[2, 4, 2000], [4, 0, 103]]); + assert.deepEqual(closest("456899 50 11992 176 272293 163 389128 96 290193 85 52"), [[13, 9, 85], [14, 3, 176]]); + assert.deepEqual(closest("239382 162 254765 182 485944 134 468751 62 49780 108 54"), [[8, 5, 134], [8, 7, 62]]); + assert.deepEqual(closest("241259 154 155206 194 180502 147 300751 200 406683 37 57"), [[10, 1, 154], [10, 9, 37]]); + assert.deepEqual(closest("89998 187 126159 175 338292 89 39962 145 394230 167 1"), [[13, 3, 175], [14, 9, 167]]); + }); +}); \ No newline at end of file