Solutions to the interview question of the week from the rendezvous with cassidoo newsletter
Solutions in the following languages:
- TypeScript
- Elixir
Inspired and forked from jda0
Solutions to the interview question of the week from the rendezvous with cassidoo newsletter
Solutions in the following languages:
Inspired and forked from jda0
/** | |
* Sort an array of strings based on the number of distinct | |
* characters that occur in the word (followed by the | |
* length of the word). | |
* | |
* $ charNumSort([“Bananas”, “do”, “not”, “grow”, “in”, “Mississippi”]) | |
* $ do in not Mississippi Bananas grow | |
* | |
*/ | |
const charNumSort = (input: Array<string>) => | |
input | |
.sort((first, second) => { | |
// use Set() to find unique char count | |
const compare = [...new Set(first)].length - [...new Set(second)].length; | |
return compare ? compare : second.length - first.length; | |
}) | |
.join(" "); | |
console.log(charNumSort(["Bananas", "do", "not", "grow", "in", "Mississippi"])); | |
// https://codesandbox.io/s/modest-sanderson-wxs33?file=/src/index.ts |
/** | |
* Given an array of random integers, move all the zeros in the array to the end of the array. | |
* Try to keep this in O(n) time (or better)! | |
* Example: | |
* $ moveZeros([1, 2, 0, 1, 0, 0, 3, 6]) | |
* $ [1, 2, 1, 3, 6, 0, 0, 0] | |
*/ | |
const moveZeros = (arr: Array<number>) => { | |
let numberOfZeroes = 0; | |
const result = arr.reduce((agg, curr) => { | |
curr ? agg.push(curr) : numberOfZeroes++; | |
return agg; | |
}, [] as number[]); | |
return [...result, ...Array(numberOfZeroes).fill(0)]; | |
}; | |
console.log(moveZeros([1, 2, 0, 1, 0, 0, 3, 6])); | |
// https://codesandbox.io/s/misty-forest-pxdog?file=/src/index.ts |
/** | |
* Given a string s and a character c, return the number of occurrences of c in s. | |
* Example: | |
* | |
* $ numChars(‘oh heavens’, ‘h’) | |
* $ 2 | |
*/ | |
const numChars = (input: string, char: string) => | |
/** | |
* yay regular expressions! global flag since we wanna count *all* instances | |
* return 0 in case of no matches | |
*/ | |
(input.match(RegExp(char, "g")) || []).length; | |
console.log(numChars("oh heavens", "h")); | |
// https://codesandbox.io/s/mystifying-swirles-8h5it?file=/src/index.ts |
/** | |
* Given an array of numbers that represent stock prices (where each number is the price for | |
* a certain day), find 2 days when you should buy and sell your stock for the highest profit. | |
* Example: | |
* | |
* $ stockBuySell([110, 180, 260, 40, 310, 535, 695]) | |
* $ “buy on day 4, sell on day 7” | |
*/ | |
const stockBuySell = (prices: Array<number>) => | |
`buy on day ${prices.indexOf(Math.min(...prices)) + 1}\ | |
, sell on day ${prices.indexOf(Math.max(...prices)) + 1}`; | |
// A much faster (the earlier one is ~88% slower, https://jsbench.me/54keiiwuvy/1) way | |
const stockBuySellReduce = (prices: Array<number>) => { | |
const minMax = prices.reduce( | |
(agg, curr, index, arr) => { | |
if (curr < arr[agg.min]) agg.min = index; | |
else if (curr > arr[agg.max]) agg.max = index; | |
return agg; | |
}, | |
{ min: 0, max: 0 } | |
); | |
return `buy on day ${minMax.min + 1}, sell on day ${minMax.max + 1}`; | |
}; | |
console.log(stockBuySell([110, 180, 260, 40, 310, 535, 695])); | |
console.log(stockBuySellReduce([110, 180, 260, 40, 310, 535, 695])); | |
// https://codesandbox.io/s/sharp-jepsen-8npl1?file=/src/index.ts |
/** | |
* Given an array of people objects (where each person has a name | |
* and a number of pizza slices they’re hungry for) and a number | |
* for the number of slices that the pizza can be sliced into, return | |
* the number of pizzas you need to buy. | |
* | |
* $ arr = [{ name: Joe, num: 9 }, { name: Cami, num: 3 }, { name: Cassidy, num: 4 }] | |
* $ gimmePizza(arr, 8) | |
* $ 2 // 16 slices needed, pizzas can be sliced into 8 pieces, so 2 pizzas should be ordered | |
*/ | |
type TPeopleSlicesMap = { | |
name: string; | |
num: number; | |
}; | |
const gimmePizza = (arr: Array<TPeopleSlicesMap>, maxSlices: number) => { | |
const totalSlices = arr.reduce((total, { num }) => { | |
return (total += num); | |
}, 0); | |
return Math.ceil(totalSlices / maxSlices); | |
}; | |
const inputMap = [ | |
{ name: "Joe", num: 9 }, | |
{ name: "Cami", num: 3 }, | |
{ name: "Cassidy", num: 4 } | |
]; | |
console.log(gimmePizza(inputMap, 8)); | |
// https://codesandbox.io/s/young-darkness-61nq3?file=/src/index.ts |
/** | |
* Given a positive integer n, write a function that returns | |
* true if it is a perfect square and false otherwise. | |
* Don’t use any built-in math functions like sqrt. | |
* Hint: Use binary search! | |
* | |
* Examples: | |
* $ perfectSquare(25) | |
* $ true | |
* | |
* $ perfectSquare(10) | |
* $ false | |
*/ | |
const isPerfectSquare = (input: number) => { | |
const binarySearchPerfectSquare = ( | |
input: number, | |
start: number, | |
end: number | |
): number | boolean => { | |
if (start > end) return false; | |
// mid value, parsed to an int using bitwise operator | |
const mid = ((start + end) / 2) >> 0; | |
if (mid * mid < input) | |
return binarySearchPerfectSquare(input, mid + 1, end); | |
if (mid * mid > input) | |
return binarySearchPerfectSquare(input, start, mid - 1); | |
// mid*mid === input, perfect square! | |
return true; | |
}; | |
return binarySearchPerfectSquare(input, 1, input); | |
}; | |
console.log(isPerfectSquare(25)); | |
console.log(isPerfectSquare(10)); | |
// https://codesandbox.io/s/relaxed-pine-yofdz?file=/src/index.ts |
/** | |
* Given an array of integers and a target value, return the number of | |
* pairs of array elements that have a difference equal to a target value. | |
* | |
* Example: | |
* $ arrayDiff([1, 2, 3, 4], 1) | |
* $ 3 // 2 - 1 = 1, 3 - 2 = 1, and 4 - 3 = 1 | |
*/ | |
const arrayDiff = (arr: Array<number>, target: number) => { | |
let count = 0, | |
flag = false; | |
arr.sort() | |
.reverse() | |
.forEach((baseNum, i, reverseSortedArr) => { | |
if (i === arr.length) return; | |
flag = false; | |
reverseSortedArr.slice(i + 1).forEach((num, j) => { | |
// arr is sorted, so we won't get the target diff again | |
if (flag) return; | |
if (j === reverseSortedArr.length) return; | |
if (baseNum - num === target) { | |
count += 1; | |
flag = true; | |
} | |
}); | |
}); | |
return count; | |
}; | |
console.log(arrayDiff([1, 2, 3, 4], 1)); | |
// https://codesandbox.io/s/cool-satoshi-84ku4?file=/src/index.ts |
/** | |
* You’re given a string of characters that are only 2s and 0s. Return the | |
* index of the first occurrence of “2020” without using the indexOf (or | |
* similar) function, and -1 if it’s not found in the string. | |
* | |
* Example: | |
* $ find2020(‘2220000202220020200’) | |
* $ 14 | |
*/ | |
const find2020 = (input: string) => { | |
let index = -1; | |
input.split("").reduce((_shouldBe2020, _curr, i) => { | |
const next4 = input.slice(i, i + 4); | |
if (next4 === "2020") index = i; | |
return next4; | |
}, input.slice(0, 4)); | |
return index; | |
}; | |
// https://codesandbox.io/s/sharp-mountain-wddiy?file=/src/index.ts |
/** | |
* Given a rowIndex, return an array of the values in that | |
* row of Pascal’s Triangle. | |
*/ | |
const getCurrentRow = (previousRow: Array<number>): Array<number> => { | |
return Array.from(Array(previousRow.length + 1)).map((_, i) => { | |
if (i === 0) return 1; | |
else if (i === previousRow.length) return 1; | |
else return previousRow[i - 1] + previousRow[i]; | |
}); | |
}; | |
const getPascalRow = (index: number): Array<number> => { | |
if (index === 0) return [1]; | |
return getCurrentRow(getPascalRow(index - 1)); | |
}; | |
console.log(getPascalRow(0)); // [1] | |
console.log(getPascalRow(1)); // [1, 1] | |
console.log(getPascalRow(2)); // [1, 2, 1] | |
console.log(getPascalRow(3)); // [1, 3, 3, 1] | |
console.log(getPascalRow(4)); // [1, 4, 6, 4, 1] | |
// https://codesandbox.io/s/heuristic-wood-qzzbd?file=/src/index.ts |
/** | |
* Given an integer n, return true if n^3 and n have the same set of digits. | |
* Example: | |
* | |
* $ sameDigits(1) // true | |
* $ sameDigits(10) // true | |
* $ sameDigits(251894) // true | |
* $ sameDigits(251895) // false | |
*/ | |
const INPUTS = [1, 10, 251894, 251895]; | |
const getUniqueDigitsAsString = (input: number) => | |
[...new Set(input.toString().split("").sort())].join(); | |
const sameDigits = (input: number) => { | |
const inputDigits = getUniqueDigitsAsString(input); | |
const cubeDigits = getUniqueDigitsAsString(Math.pow(input, 3)); | |
return inputDigits === cubeDigits; | |
}; | |
INPUTS.forEach(input => console.log(sameDigits(input))) | |
// true, true, true, false | |
// https://codesandbox.io/s/cold-cdn-85qcb?file=/src/index.ts |
/** | |
* Given a list, return a list of all its prefixes in ascending order of their | |
* length. You’re essentially implementing the inits function in Haskell! | |
* | |
* Example: | |
* $ inits([4, 3, 2, 1]) | |
* $ [[], [4], [4,3], [4,3,2], [4,3,2,1]] | |
* | |
* $ inits([144]) | |
* $ [[], [144]] | |
*/ | |
const INPUT = [4, 3, 2, 1]; | |
const inits = (input: Array<number>) => | |
input.reduce( | |
(arr, curr, index) => { | |
arr.push([...arr[index], curr]); | |
return arr; | |
}, | |
[[]] as number[][] | |
); | |
console.log(inits(INPUT)); | |
// https://codesandbox.io/s/determined-swanson-qn27b?file=/src/index.ts |
/** | |
* Given a direction and a number of columns, write a function that outputs an | |
* arrow of asterisks (see the pattern in the examples below)! | |
* | |
* Example: | |
* | |
* $ printArrow('right', 3) | |
* Output: | |
* | |
* | |
* | |
* | |
* | |
* $ printArrow('left', 5) | |
* Output: | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
*/ | |
const printArrow = (direction: "right" | "left", len: number) => { | |
Array.from(Array(2 * (len - 1) + 1)).forEach((_, index) => { | |
let numSpaces; | |
if (direction === "right") { | |
numSpaces = index > len - 1 ? 2 * len - 2 - index : index; | |
} else { | |
numSpaces = len - (index > len - 1 ? 2 * len - 1 - index : index + 1); | |
} | |
console.log(`${" ".repeat(numSpaces)}*`); | |
}); | |
}; | |
// https://codesandbox.io/s/gifted-perlman-0yvo0?file=/src/index.ts |
const LINE = "█".repeat(10); | |
const PRIDE_COLORS = [ | |
"#e40303", | |
"#ff8c00", | |
"#ffed00", | |
"#008026", | |
"#004dff", | |
"#750787" | |
]; | |
const PrideFlag = () => { | |
PRIDE_COLORS.forEach((color) => { | |
console.log(`%c${LINE}`, `color: ${color}`); | |
}); | |
}; | |
PrideFlag(); | |
// https://codesandbox.io/s/blissful-leavitt-86k1s?file=/src/index.ts |
/** | |
* Write a function to find the longest common prefix string in an array of | |
* strings. | |
* | |
* Example: | |
* | |
* $ longestPrefix(["cranberry","crawfish","crap"]) | |
* $ "cra" | |
* | |
* $ longestPrefix(["parrot", "poodle", "fish"]) | |
* $ "" | |
*/ | |
function longestPrefix(input: Array<string>) { | |
let result = ""; | |
input[0].split("").reduce((prefix, currentLetter) => { | |
const isPrefixValid = input.every((word) => word.startsWith(prefix)); | |
if (isPrefixValid) { | |
result = prefix; | |
return `${prefix}${currentLetter}`; | |
} | |
return result; | |
}, ""); | |
return result; | |
} | |
// https://codesandbox.io/s/heuristic-dan-pl0nn?file=/src/index.ts |
/** | |
* An “odious number” is a non-negative number that has an | |
* odd number of 1s in its binary expansion. Write a | |
* function that returns true if a given number is odious. | |
* | |
* Example: | |
* | |
* $ isOdious(14) | |
* $ true | |
* | |
* $ isOdious(5) | |
* $ false | |
*/ | |
const isOdious = (input: number) => | |
(input.toString(2).match(/1/g) ?? []).length % 2 === 1; | |
// https://codesandbox.io/s/admiring-poitras-8l6sd?file=/src/index.ts |
/** | |
* Given an array of objects A, and an array of indexes B, | |
* reorder the objects in array A with the given indexes | |
* in array B. | |
* | |
* Example: | |
* | |
* let a = [C, D, E, F, G, H]; | |
* let b = [3, 0, 4, 1, 2, 5]; | |
* | |
* $ reorder(a, b) // a is now [D, F, G, C, E, H] | |
*/ | |
const reorder = ( | |
a: Array<Record<string, unknown> | string>, | |
b: Array<number> | |
) => | |
[...Array(a.length)].reduce((res, _, index) => { | |
res[b[index]] = a[index]; | |
return res; | |
}, []); | |
// https://codesandbox.io/s/agitated-bash-tmu25?file=/src/index.ts |
defmodule RWC_259 do | |
@doc """ | |
Given an integer n, count the total number of 1 digits appearing in all | |
non-negative integers less than or equal to n. | |
Example: | |
> numberOfOnes(14) | |
> 7 // 1, 10, 11, 12, 13, 14 | |
""" | |
defp count_one_recursively(input, count) when input == 1, do: count + 1 | |
defp count_one_recursively(input, count) do | |
input | |
|> Integer.to_string() | |
|> String.split("") | |
|> Enum.count(&(&1 == "1")) | |
|> then(fn x -> | |
case x > 0 do | |
true -> | |
count_one_recursively(input - 1, count + x) | |
_ -> | |
count_one_recursively(input - 1, count) | |
end | |
end) | |
end | |
def number_of_ones(input) do | |
input | |
|> count_one_recursively(0) | |
|> IO.puts() | |
end | |
end | |
RWC_259.number_of_ones(14) |
defmodule RWC_270 do | |
@doc """ | |
Let’s say you have n doors that start out as closed. With the first pass | |
across the doors, you toggle every door open. With the second pass, you | |
toggle every second door. With the third, every third door, and so on. | |
Write a function that takes in an integer numberOfPasses, and returns how | |
many doors are open after the number of passes. | |
Example: | |
let n = 7 | |
let numberOfPasses = 3 | |
> passDoors(n, numberOfPasses) | |
> 4 | |
// Explanation: | |
// 0 means open, 1 means closed | |
// Initial: 1 1 1 1 1 1 1 | |
// Pass 1: 0 0 0 0 0 0 0 | |
// Pass 2: 0 1 0 1 0 1 0 | |
// Pass 3: 0 1 1 1 0 0 0 | |
""" | |
@spec pass_doors(n :: non_neg_integer, number_of_passes :: non_neg_integer) :: non_neg_integer | |
def pass_doors(n, number_of_passes) do | |
1..number_of_passes | |
# duplicate with n+1 because map_every/3 starts from first elem indexed 0 | |
# open => true, closed => false | |
|> Enum.reduce(List.duplicate(false, n + 1), fn nth, doors -> | |
Enum.map_every(doors, nth, &(not &1)) | |
end) | |
# ignore the extra door we added at the start | |
|> Enum.drop(1) | |
|> Enum.count(& &1) | |
end | |
end | |
RWC_270.pass_doors(7, 3) |
defmodule RWC_281 do | |
@doc """ | |
Given an array of integers arr and an integer n, return a subarray | |
of arr of length n where the sum is the largest. | |
Make sure you maintain the order of the original array, and if n | |
is greater than arr.length, you can choose what you want to return. | |
> maxSubarray([-4,2,-5,1,2,3,6,-5,1], 4) | |
> [1,2,3,6] | |
> maxSubarray([1,2,0,5], 2) | |
> [0,5] | |
""" | |
def maxSubarray(input, size) do | |
input | |
|> Enum.chunk_every(size, 1, :discard) | |
|> Enum.max_by(&Enum.sum(&1)) | |
end | |
end | |
IO.inspect(RWC_281.maxSubarray([-4, 2, -5, 1, 2, 3, 6, -5, 1], 4)) | |
IO.inspect(RWC_281.maxSubarray([1, 2, 0, 5], 2)) |
defmodule RWC_282 do | |
@doc """ | |
Given a number, sum every second digit in that number. | |
Example: | |
> sumEveryOther(548915381) | |
> 26 // 4+9+5+8 | |
> sumEveryOther(10) | |
> 0 | |
> sumEveryOther(1010.11) | |
> 1 // 0+0+1 | |
""" | |
def sumEveryOther(input) do | |
input | |
|> to_string() | |
|> String.graphemes() | |
|> List.delete_at(0) | |
|> Enum.filter(&(&1 !== ".")) | |
|> Enum.take_every(2) | |
|> Enum.map(&String.to_integer/1) | |
|> Enum.sum() | |
end | |
end |
defmodule RWC_284 do | |
@doc """ | |
You are given a list of positive integers which represents some | |
range of integers which has been truncated. Find the missing bits, | |
insert ellipses to show that that part has been truncated, and | |
print it. If the consecutive values differ by exactly two, | |
then insert the missing value. | |
Examples: | |
> missingBits([1,2,3,4,20,21,22,23]) | |
> "[1,2,3,4,...,20,21,22,23]" | |
> missingBits([1,2,3,5,6]) | |
> "[1,2,3,4,5,6]" | |
> missingBits([1,3,20,27]) | |
> "[1,2,3,...,20,...,27]" | |
""" | |
def missingBits(input) do | |
input | |
|> Enum.with_index() | |
|> then(fn input_with_index -> | |
input_with_index | |
|> Enum.reduce([], fn {num, index}, acc -> | |
{next_num, _} = Enum.at(input_with_index, index + 1, {num, nil}) | |
case next_num - num do | |
# Last index | |
0 -> [num | acc] | |
1 -> [num | acc] | |
# When step is exactly two | |
2 -> [num + 1, num | acc] | |
_ -> ["...", num | acc] | |
end | |
end) | |
|> Enum.reverse() | |
|> Enum.join(",") | |
|> then(&"[#{&1}]") | |
end) | |
end | |
end |
defmodule RWC_285 do | |
@doc """ | |
Given a positive integer, generate an array in which every | |
element is an array that goes from 1 to the index of that array. | |
Example: | |
> generateArrays(4) | |
> [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]] | |
> generateArrays(1) | |
> [[1]] | |
""" | |
def generateArrays(input) do | |
1..input | |
|> Enum.to_list() | |
|> Enum.map(&Enum.to_list(1..&1)) | |
end | |
end |
defmodule RWC_286 do | |
@doc """ | |
Spreadsheet programs often use the A1 Reference Style to refer to columns. | |
Given a column name in this style, return its column number. | |
Examples of column names to their numbers: | |
A -> 1 | |
B -> 2 | |
C -> 3 | |
// etc | |
Z -> 26 | |
AA -> 27 | |
AB -> 28 | |
// etc | |
AAA -> 703 | |
""" | |
def get_weight(char, power) do | |
char | |
|> String.to_charlist() | |
|> hd() | |
# A => 65, B => 66, so on... | |
|> then(&(&1 - 64)) | |
|> then(&(&1 * 26 ** power)) | |
end | |
def recusively_get_weight([{char, index}]), do: get_weight(char, index) | |
def recusively_get_weight([left | rest]), | |
do: recusively_get_weight([left]) + recusively_get_weight(rest) | |
def get_column_number(input) do | |
input | |
|> String.split("", trim: true) | |
|> Enum.reverse() | |
|> Enum.with_index() | |
|> recusively_get_weight() | |
end | |
end |
defmodule RWC_287 do | |
@doc """ | |
Print the digits 0 through 100 without using the characters | |
1, 2, 3, 4, 5, 6, 7, 8, or 9 in your code. Get creative! | |
""" | |
def print_digits() do | |
hundred = | |
"d" | |
|> to_charlist() | |
|> hd() | |
zero = | |
[hundred - hundred] | |
|> hd() | |
zero..hundred | |
|> Enum.join(", ") | |
end | |
end |
defmodule RWC_288 do | |
@doc """ | |
Given a string of parenthesis, return the number of parenthesis | |
you need to add to the string in order for it to be balanced. | |
Examples: | |
> numBalanced(`()`) | |
> 0 | |
> numBalanced(`(()`) | |
> 1 | |
> numBalanced(`))()))))()`) | |
> 6 | |
> numBalanced(`)))))`) | |
> 5 | |
""" | |
def num_balanced(input) do | |
input | |
|> String.split("", trim: true) | |
|> Enum.frequencies() | |
|> Map.values() | |
|> then( | |
&case &1 do | |
[only_one_kind] -> only_one_kind | |
[one, other] -> abs(one - other) | |
end | |
) | |
end | |
end |
defmodule RWC_289 do | |
@doc """ | |
Given a list of numbers, return all groups of repeating consecutive numbers. | |
Examples: | |
> repeatedGroups([1, 2, 2, 4, 5]) | |
[[2, 2]] | |
> repeatedGroups([1, 1, 0, 0, 8, 4, 4, 4, 3, 2, 1, 9, 9]) | |
[[1, 1], [0, 0], [4, 4, 4], [9, 9]] | |
""" | |
def chunk_repeats([head | rest]), do: chunk_repeats(rest, [[head]]) | |
def chunk_repeats([], done), do: done | |
def chunk_repeats([head | rest], [[head | head_repeated] | previously_repeated]), | |
do: chunk_repeats(rest, [[head | [head | head_repeated]] | previously_repeated]) | |
def chunk_repeats([head | rest], previously_repeated), | |
do: chunk_repeats(rest, [[head] | previously_repeated]) | |
def repeated_groups(input) do | |
input | |
|> chunk_repeats() | |
|> Enum.reverse() | |
|> Enum.filter(&(length(&1) > 1)) | |
end | |
end |
defmodule RWC_300 do | |
@doc """ | |
Write a function to find out whether the binary representation of | |
a number is palindrome or not. | |
Example: | |
> binaryPal(5) | |
> true | |
> binaryPal(10) | |
> false | |
""" | |
def binary_pal(input) do | |
input | |
|> Integer.to_charlist(2) | |
|> List.to_string() | |
|> then(fn digits -> | |
digits | |
|> String.reverse() | |
|> then( | |
&case &1 do | |
^digits -> true | |
_ -> false | |
end | |
) | |
end) | |
end | |
end |
defmodule RWC_301 do | |
@doc """ | |
Given a string, calculate the score that it would get in a game of Scrabble. | |
For extra credit, try verifying if the string is a valid word, or take into | |
account premium squares! | |
Scoring and example: | |
1 point: E, A, I, O, N, R, T, L, S, U | |
2 points: D, G | |
3 points: B, C, M, P | |
4 points: F, H, V, W, Y | |
5 points: K | |
8 points: J, X | |
10 points: Q, Z | |
> scrabbleScore('FIZZBUZZ') | |
> 49 | |
""" | |
@score_map %{ | |
"EAIONRTLSU" => 1, | |
"DG" => 2, | |
"BCMP" => 3, | |
"FHVWY" => 4, | |
"K" => 5, | |
"JX" => 8, | |
"QZ" => 10 | |
} | |
def scrabble_score(input) do | |
input | |
|> String.split("", trim: true) | |
|> Enum.reduce(0, fn letter, score -> | |
@score_map | |
|> Map.keys() | |
|> Enum.find(&String.contains?(&1, letter)) | |
|> then(&Map.get(@score_map, &1)) | |
|> Kernel.+(score) | |
end) | |
end | |
end |
defmodule RWC_303 do | |
@doc """ | |
Given an array of people objects (where each person has a name and a number of | |
pie pieces they’re hungry for) and a number for the number of pieces that the | |
pie can be cut into, return the number of pies you need to buy. | |
Example: | |
iex> | |
...> arr = [ | |
...> %{ name: Joe, num: 9 }, | |
...> %{ name: Cami, num: 3 }, | |
...> %{ name: Cassidy, num: 4 } | |
...> ] | |
iex> RWC_303.num_pie(arr, 8) | |
2 # 16 pieces needed, pies can be cut into 8 pieces, so 2 pies should be bought | |
""" | |
def num_pie(input, count) do | |
input | |
|> Enum.reduce(0, &(&2 + &1[:num])) | |
|> div(count) | |
end | |
end |
defmodule RWC_304 do | |
@doc """ | |
Given an array arr and integers n and m, remove n elements | |
from the front of the array, and m elements from the back. | |
Assume that n + m <= arr.length. | |
Example: | |
iex> RWC_304.trim_array([1, 2, 3, 4, 5, 6], 2, 1) | |
[3, 4, 5] | |
iex> RWC_304.trim_array([6, 2, 4, 3, 7, 1, 3], 5, 0) | |
[1, 3] | |
iex> RWC_304.trim_array([1, 7], 0, 0) | |
[1, 7] | |
""" | |
def trim_array(input, n, m) do | |
input | |
|> Enum.slice(n, length(input) - n - m) | |
end | |
end |
defmodule RWC_305 do | |
@doc """ | |
Given some JSON data, calculate the maximum depth reached. Both arrays | |
and dictionaries increase the depth! If the input is invalid data, the | |
response should be undefined (you decide how you want that to return). | |
iex> RWC_305.depth_json([]) | |
1 | |
iex> RWC_305.depth_json([1, 2, 3, 4, 5]) | |
1 | |
iex> RWC_305.depth_json([%{a: []}, ["abc"]]) | |
3 | |
""" | |
def depth_json(input), do: compute_depth(input) | |
defp compute_depth(input) when is_list(input) or is_map(input) do | |
cond do | |
is_list(input) and input == [] -> | |
1 | |
true -> | |
input | |
|> flatten_if_map() | |
|> Enum.map(&compute_depth/1) | |
|> Enum.max() | |
|> Kernel.+(1) | |
end | |
end | |
defp compute_depth(_), do: 0 | |
defp flatten_if_map(input) when is_map(input), do: Map.values(input) | |
defp flatten_if_map(input), do: input | |
end |
defmodule RWC_306 do | |
@doc """ | |
Write a function that takes an array of consecutive, increasing letters as input, | |
and returns any missing letters in the array between the first and last letter. | |
Example: | |
iex> RWC_306.missing_letters(["a","b","c","d","f"]) | |
["e"] | |
iex> RWC_306.missing_letters(["a","b","c","d","e","h","i","j","k","l","m","n","o", | |
...> "p","q","r","s","t","u","w","x","y","z"]) | |
["f","g","v"] | |
""" | |
def missing_letters(input) do | |
input_complete_mapset = | |
input | |
|> then(fn list -> | |
[head | _] = list | |
tail = List.last(list) | |
hd(to_charlist(head))..hd(to_charlist(tail)) | |
|> MapSet.new() | |
end) | |
input_mapset = | |
input | |
|> MapSet.new(&hd(to_charlist(&1))) | |
input_complete_mapset | |
|> MapSet.difference(input_mapset) | |
|> MapSet.to_list() | |
|> List.to_string() | |
|> String.graphemes() | |
end | |
end |
defmodule RWC_307 do | |
@doc """ | |
Given an integer n, return true if it's a perfect | |
square AND when reversed, is still a perfect square. | |
iex> RWC_307.reversed_squares(9) | |
true | |
iex> RWC_307.reversed_squares(441) | |
true | |
iex> RWC_307.reversed_squares(25) | |
false | |
""" | |
def reversed_squares(input) do | |
input | |
|> Integer.digits() | |
|> Enum.reverse() | |
|> Integer.undigits() | |
|> then( | |
&cond do | |
is_perfect_square(&1) and is_perfect_square(input) -> true | |
true -> false | |
end | |
) | |
end | |
defp is_perfect_square(input) do | |
input | |
|> :math.sqrt() | |
|> then(&if Kernel.trunc(&1) == &1, do: true, else: false) | |
end | |
end |
defmodule RWC_308 do | |
@doc """ | |
Given an array of strings and a max width, format the text such that each line has exactly | |
maxWidth characters and is fully justified. You can choose how you want to wrap a word. | |
Example: | |
iex> RWC_308.justify_text(["This", "is", "an", "example", "of", "text", "justification."], 16) | |
[ | |
"This is an", | |
"example of text", | |
"justification. " | |
] | |
""" | |
def justify_text(input, max_length) do | |
input | |
|> Enum.reduce([[]], fn word, phrase_list -> | |
phrase_list | |
|> List.last([]) | |
|> then(fn last_phrase -> | |
current_phrase_length = last_phrase |> Enum.join(".") |> String.length() | |
cond do | |
current_phrase_length + String.length(word) < max_length -> | |
# update last element | |
last_list = | |
phrase_list | |
|> Enum.at(-1) | |
|> Enum.concat([word]) | |
phrase_list | |
|> Enum.drop(-1) | |
|> Enum.concat([last_list]) | |
true -> | |
# move to new phrase | |
phrase_list | |
|> Enum.concat([[word]]) | |
end | |
end) | |
end) | |
|> Enum.map(&justify_phrase(&1, max_length)) | |
end | |
defp justify_phrase(input, max_length) do | |
number_of_spaces_to_add = max_length - (input |> Enum.join("") |> String.length()) | |
number_of_breaks = if length(input) == 1, do: 1, else: length(input) - 1 | |
each_space_block_length = div(number_of_spaces_to_add, number_of_breaks) | |
remainder = rem(number_of_spaces_to_add, number_of_breaks) | |
spaces_list = | |
" " | |
|> list_from(each_space_block_length) | |
|> list_from(number_of_breaks) | |
|> then(fn [first_break_spaces | rest] -> | |
case remainder do | |
0 -> | |
[first_break_spaces | rest] | |
_ -> | |
first_break_spaces | |
|> Enum.concat(list_from(" ", remainder)) | |
|> then(&[&1 | rest]) | |
end | |
end) | |
|> then( | |
&cond do | |
length(input) == 1 -> &1 | |
true -> Enum.concat(&1, [[""]]) | |
end | |
) | |
input | |
|> Enum.zip(spaces_list) | |
|> Enum.reduce("", fn {word, spaces}, line -> | |
"#{line}#{word}#{Enum.join(spaces)}" | |
end) | |
end | |
defp list_from(el, count), do: for(_ <- 1..count, do: el) | |
end |
defmodule RWC_309 do | |
@doc """ | |
Given a string, separate it into groups of non-space equal characters, sorted. | |
Example: | |
iex> RWC_309.explode_string("Ahh, abracadabra!") | |
["!",",","A","aaaaa","bb","c","d","hh","rr"] | |
""" | |
def explode_string(input) do | |
input | |
|> String.replace(" ", "") | |
|> String.split("", trim: true) | |
|> Enum.frequencies() | |
|> Map.to_list() | |
|> Enum.map(fn {char, count} -> | |
list_from(char, count) | |
|> Enum.join() | |
end) | |
end | |
defp list_from(el, count), do: for(_ <- 1..count, do: el) | |
end |
defmodule RWC_310 do | |
@doc """ | |
Given an array where each element is the price of a given stock on that index's day, | |
choose a single day to buy a stock and a different day (in the future/later in the array) | |
to sell the stock to maximize your profit. Return the maximum profit that you can get | |
from a given input. If you can't profit, return 0. | |
Example: | |
iex> RWC_310.maximum_profit([7, 1, 5, 3, 6, 4]) | |
5 # Buy on day 2, and sell on day 5, your profit = 6 - 1 = 5. | |
""" | |
def maximum_profit(input) do | |
input | |
|> Enum.with_index() | |
|> Enum.reduce(0, fn {price, index}, max_profit -> | |
input | |
|> Enum.slice((index + 1)..-1) | |
|> Enum.max(&>=/2, fn -> 0 end) | |
|> Kernel.-(price) | |
|> then( | |
&cond do | |
&1 > max_profit -> &1 | |
true -> max_profit | |
end | |
) | |
end) | |
end | |
end |
defmodule RWC_311 do | |
@doc """ | |
Given two strings s and t, return true if t is an anagram of s, and false otherwise. | |
Try this in a language you're not comfortable with! | |
Example: | |
iex> RWC_311.is_anagram("barbie", "oppenheimer") | |
false | |
iex> RWC_311.is_anagram("race", "care") | |
true | |
""" | |
def is_anagram(a, b), do: get_chars(a) === get_chars(b) | |
defp get_chars(input), do: input |> String.split("", trim: true) |> Enum.frequencies() | |
end |
defmodule RWC_312 do | |
@doc """ | |
Implement the Luhn algorithm to validate a credit card number. | |
Bonus points if you can identify what brand of credit card the user inputted! | |
iex> RWC_312.luhn_check(123456789) | |
false | |
iex> RWC_312.luhn_check(5555555555554444) | |
true | |
""" | |
def luhn_check(input) do | |
input | |
|> Integer.digits() | |
|> Enum.with_index(1) | |
|> Enum.reduce(0, fn {digit, index}, sum -> | |
cond do | |
rem(index, 2) == 0 -> digit * 2 | |
true -> digit | |
end | |
|> Integer.digits() | |
|> Enum.sum() | |
|> Kernel.+(sum) | |
end) | |
|> then(&(rem(&1, 10) == 0)) | |
end | |
end |
defmodule RWC_313 do | |
@doc """ | |
You have a faulty keyboard. Whenever you type a vowel on it (a,e,i,o,u,y), | |
it reverses the string that you have written, instead of typing the character. | |
Typing other characters works as expected. Given a string, return what will be | |
on the screen after typing with your faulty keyboard. | |
Example: | |
iex> RWC_313.faulty_keeb("string") | |
"rtsng" | |
iex> RWC_313.faulty_keeb("hello world!") | |
"w hllrld!" | |
""" | |
@vowels ["a", "e", "i", "o", "u", "y"] | |
def faulty_keeb(input) do | |
input | |
|> String.graphemes() | |
|> Enum.reduce([], fn char, word -> | |
cond do | |
Enum.member?(@vowels, char) -> Enum.reverse(word) | |
true -> Enum.concat(word, [char]) | |
end | |
end) | |
|> Enum.join() | |
end | |
end |
defmodule RWC_314 do | |
@doc """ | |
Make a "guessing game" where there is a target number, and as the user makes | |
guesses, the output returns higher or lower until the user is correct. | |
Example usage: | |
Guess the number! | |
> 10 | |
higher | |
> 20 | |
higher | |
> 30 | |
lower | |
> 25 | |
higher | |
> 27 | |
Correct! You won in 5 guesses! | |
""" | |
def solve(guess) do | |
IO.puts("Guess the number!") | |
input() | |
|> solve(guess) | |
end | |
def solve(guess, answer, guess_count \\ 1) | |
def solve(guess, answer, 1) when guess === answer, | |
do: IO.puts("Correct! You won in 1 guess!") |> exit() | |
def solve(guess, answer, guess_count) when guess === answer, | |
do: IO.puts("Correct! You won in #{guess_count} guesses!") |> exit() | |
def solve(guess, answer, guess_count) do | |
cond do | |
guess > answer -> | |
IO.puts("lower") | |
guess < answer -> | |
IO.puts("higher") | |
end | |
input() | |
|> solve(answer, guess_count + 1) | |
end | |
defp input() do | |
IO.gets("> ") | |
|> Integer.parse() | |
|> then(&elem(&1, 0)) | |
end | |
end | |
RWC_314.solve(:rand.uniform(100)) |
defmodule RWC_315 do | |
@moduledoc """ | |
Given a sequence of numbers, generate a "count and say" string. | |
Example: | |
iex> RWC_315.count_and_say(112222555) | |
"two 1s, then four 2s, then three 5s" | |
iex> RWC_315.count_and_say(3333333333) | |
"ten 3s" | |
""" | |
@number_say_map %{ | |
1 => "one", | |
2 => "two", | |
3 => "three", | |
4 => "four", | |
5 => "five", | |
6 => "six", | |
7 => "seven", | |
8 => "eight", | |
9 => "nine", | |
10 => "ten" | |
} | |
def count_and_say(input) do | |
input | |
|> Integer.digits() | |
# count | |
|> Enum.reduce([], fn number, list -> | |
current_list = List.first(list, [nil]) | |
current_list | |
|> List.first() | |
|> then(fn current_digit -> | |
case current_digit do | |
# same digit as current | |
^number -> | |
list | |
|> List.delete_at(0) | |
|> then(&[[number | current_list] | &1]) | |
# new digit | |
_ -> | |
[[number] | list] | |
end | |
end) | |
end) | |
|> Enum.reverse() | |
# say | |
|> Enum.map_join(", then ", fn list -> | |
len = Map.get(@number_say_map, length(list)) | |
"#{len} #{List.first(list)}s" | |
end) | |
end | |
end |
defmodule RWC_316 do | |
@moduledoc """ | |
Given an array of integers and a number k (where k is guaranteed to be less | |
than the array's length), return a subarray of length k with the minimum | |
possible sum. Maintain the order of the original array! | |
Example: | |
iex> RWC_316.min_subs([1, 3, 20, 4, 8, 9, 11], 3) | |
[4, 8, 9] | |
iex> RWC_316.min_subs([4, 4, 4, 4, 8], 2) | |
[4, 4] | |
""" | |
def min_subs(input, len) do | |
input | |
|> Enum.chunk_every(len, 1, :discard) | |
|> Enum.min_by(&Enum.sum/1) | |
end | |
end |
defmodule RWC_317 do | |
@moduledoc """ | |
Given an array of integers, sort them into two separate sorted | |
arrays of even and odd numbers. If you see a zero, skip it. | |
Example: | |
iex> RWC_317.separate_and_sort([4, 3, 2, 1, 5, 7, 8, 9]) | |
[[2, 4, 8], [1, 3, 5, 7, 9]] | |
iex> RWC_317.separate_and_sort([1,1,1,1]) | |
[[], [1,1,1,1]] | |
""" | |
def separate_and_sort(input) do | |
input | |
|> Enum.sort() | |
|> Enum.split_with(&(rem(&1, 2) == 0)) | |
|> Tuple.to_list() | |
end | |
end |
defmodule RWC_318 do | |
@moduledoc """ | |
You have n equal-sized blocks and you want to build a staircase | |
with them. Return the number of steps you can fully build. | |
iex> RWC_318.build_staircase(6) | |
3 | |
#=> # | |
#=> ## | |
#=> ### | |
iex> RWC_318.build_staircase(9) | |
3 #=> it takes 10 blocks to make 4 steps | |
""" | |
def build_staircase(input) do | |
1..input | |
|> Enum.reduce_while(0, fn step, total -> | |
cond do | |
total + step > input -> {:halt, step - 1} | |
true -> {:cont, total + step} | |
end | |
end) | |
end | |
end |
defmodule RWC_322 do | |
@moduledoc """ | |
Given two strings s and t, determine if they are isomorphic. | |
Two strings are isomorphic if there is a one-to-one mapping | |
possible for every character of the first string to every | |
character of the second string. | |
iex> RWC_322.is_isomorphic("abb", "cdd") | |
true # "a" maps to "c" and "b" maps to "d" | |
iex> RWC_322.is_isomorphic("cassidy", "1234567") | |
false # "s" cannot have a mapping to both "3" and "4" | |
iex> RWC_322.is_isomorphic("cass", "1233") | |
true | |
""" | |
def is_isomorphic(first, second) do | |
[first, second] | |
|> Enum.map(fn string -> | |
string | |
|> String.split("", trim: true) | |
|> Enum.frequencies() | |
|> Map.values() | |
end) | |
|> then(fn [f1, f2] -> f1 == f2 end) | |
end | |
end |
defmodule RWC_323 do | |
@moduledoc """ | |
Given a string s, you are allowed to delete at most k characters. | |
Find if the string can be a palindrome after deleting at most k characters. | |
iex> RWC_323.k_pal("abcweca", 2) | |
true | |
iex> RWC_323.k_pal("abcweca", 1) | |
false | |
iex> RWC_323.k_pal("acwca", 2) | |
true | |
iex> RWC_323.k_pal("acxcb", 1) | |
false | |
""" | |
def k_pal(string, count) do | |
string | |
|> String.graphemes() | |
|> check_first_and_last_characters(count) | |
end | |
defp check_first_and_last_characters([_char], _count), do: true | |
defp check_first_and_last_characters([char | [char]], _count), do: true | |
defp check_first_and_last_characters(string, count) do | |
[first | with_last] = string | |
[last | remaining_reversed] = Enum.reverse(with_last) | |
remaining = Enum.reverse(remaining_reversed) | |
cond do | |
first == last -> | |
check_first_and_last_characters(remaining, count) | |
first != last and count == 0 -> | |
false | |
first != last and count > 0 -> | |
check_first_and_last_characters([first | remaining], count - 1) or | |
check_first_and_last_characters(with_last, count - 1) | |
true -> | |
false | |
end | |
end | |
end |
defmodule RWC_325 do | |
@moduledoc """ | |
Given a list of words and a dictionary of letter scores, find | |
the word with the highest score according to the rules: | |
score = word_length * (sum of letter scores in the word) | |
If there are multiple words with the same highest score, | |
return the lexicographically smallest one. | |
iex> word_list = ["apple", "banana", "cherry", "date", "fig"]; | |
...> RWC_325.score_word_game(word_list) | |
"cherry" | |
""" | |
def score_word_game(word_list, _letter_scores \\ nil) do | |
word_list | |
|> Enum.map(&get_word_score/1) | |
|> Enum.max_by(fn {_word, score} -> score end) | |
|> then(&elem(&1, 0)) | |
end | |
defp get_word_score(word) do | |
word | |
|> String.downcase() | |
|> String.graphemes() | |
|> Enum.reduce(0, fn letter, total -> | |
score = (to_charlist(letter) |> hd()) - 96 | |
total + score | |
end) | |
|> then(&{word, &1}) | |
end | |
end |
defmodule RWC_326 do | |
@moduledoc """ | |
Given a list of tasks, where each task has a duration, and a limited amount | |
of available time to work, write a function to return the tasks that can be | |
completed within the given time, without re-ordering the original list of tasks. | |
Try to maximize the number of tasks that can be completed! | |
Example: | |
iex> tasks = [ | |
...> %{ name: "Task 1", duration: 4 }, | |
...> %{ name: "Task 2", duration: 2 }, | |
...> %{ name: "Task 3", duration: 7 }, | |
...> %{ name: "Task 4", duration: 5 }, | |
...> %{ name: "Task 5", duration: 1 }, | |
...> %{ name: "Task 6", duration: 3 } | |
...> ]; | |
...> time_to_work = 6; | |
...> RWC_326.do_tasks(tasks, time_to_work) | |
["Task 2", "Task 5", "Task 6"] | |
""" | |
def do_tasks(task_list, time_to_work) do | |
task_list | |
|> Enum.with_index() | |
|> Enum.sort_by(fn {%{duration: duration}, _index} -> duration end) | |
|> Enum.reduce_while({0, []}, fn {%{duration: duration}, index}, {time_sum, indices} -> | |
cond do | |
time_sum + duration > time_to_work -> {:halt, indices} | |
true -> {:cont, {time_sum + duration, [index | indices]}} | |
end | |
end) | |
|> Enum.sort() | |
|> Enum.map( | |
&(task_list | |
|> Enum.at(&1) | |
|> then(fn %{name: name} -> name end)) | |
) | |
end | |
end |
defmodule RWC_327 do | |
@moduledoc """ | |
Given a start number a, an ending number b, and a string str that can | |
be "odd", "even", or "prime", return all of the numbers that are odd, even, | |
or prime between a and b. a will not always necessarily be less than b! | |
iex> RWC_327.between_nums(3, 11, "even") | |
[4,6,8,10] | |
iex> RWC_327.between_nums(15, 1, "prime") | |
[2,3,5,7,11,13] | |
""" | |
defp is_prime(num) do | |
cond do | |
num <= 1 -> | |
false | |
num == 2 -> | |
true | |
rem(num, 2) == 0 -> | |
false | |
true -> | |
3..(num - 1)//2 | |
|> Enum.all?(&(rem(num, &1) != 0)) | |
end | |
end | |
def between_nums(start, finish, option) when start > finish, | |
do: between_nums(finish, start, option) | |
def between_nums(start, finish, option) do | |
start..finish | |
|> Enum.filter(fn num -> | |
case option do | |
"prime" -> | |
is_prime(num) | |
"even" -> | |
rem(num, 2) == 0 | |
_ -> | |
rem(num, 2) != 0 | |
end | |
end) | |
end | |
end |
defmodule RWC_328 do | |
@moduledoc """ | |
Given two arrays calories and prices, where calories[i] and prices[i] | |
represent the calorie content and price of the ith food item, and a | |
daily calorie goal, find the minimum cost to achieve or exceed the daily | |
calorie goal. If it's impossible to meet the goal, return -1. | |
Example: | |
iex> calories = [200, 400, 600, 800] | |
...> prices = [50, 60, 80, 100] | |
...> daily_goal = 1200 | |
...> RWC_328.min_cost_for_calories(calories, prices, daily_goal) | |
160 # the 2nd and 4th items add up to 1200 calories for the minimum cost | |
""" | |
def min_cost_for_calories(calories, prices, daily_goal) do | |
calories | |
|> Enum.with_index() | |
|> Enum.flat_map(fn {calorie, index} -> | |
calories | |
|> Enum.with_index() | |
|> Enum.slice(index..-1) | |
|> Enum.filter(&(elem(&1, 0) != calorie)) | |
|> Enum.map(&{elem(&1, 0) + calorie, {index, elem(&1, 1)}}) | |
end) | |
|> Enum.filter(&(elem(&1, 0) >= daily_goal)) | |
|> Enum.reduce(:infinity, fn {_calories, {index_a, index_b}}, total_price -> | |
current_combo_price = Enum.at(prices, index_a) + Enum.at(prices, index_b) | |
cond do | |
current_combo_price < total_price -> current_combo_price | |
true -> total_price | |
end | |
end) | |
end | |
end |
defmodule RWC_329 do | |
@moduledoc """ | |
There is a sorted integer array that has been rotated an unknown number of times. | |
Given that rotated array, return how many times it has been rotated. | |
It may contain duplicate numbers! | |
iex> RWC_329.rotated_num([4, 0, 1, 2, 3]) | |
1 | |
iex> RWC_329.rotated_num([7, 9, 20]) | |
0 | |
iex> RWC_329.rotated_num([7, 7, 314, 1337, 7]) | |
4 | |
""" | |
def rotated_num(nums) do | |
cond do | |
Enum.sort(nums) == nums -> 0 | |
true -> 1 + rotated_num(Enum.slide(nums, 0, -1)) | |
end | |
end | |
end |
defmodule RWC_330 do | |
@moduledoc """ | |
Given an array of integers, return the majority element. If there is no | |
majority element, return if the array is majority even or odd numbers, | |
and if there is none, say so. | |
iex> RWC_330.majority([3,1,4,1]) | |
"1" | |
iex> RWC_330.majority([33,44,55,66,77]) | |
"Majority odds" | |
iex> RWC_330.majority([1,2,3,4]) | |
"No majority" | |
""" | |
def majority(nums) do | |
nums | |
|> Enum.frequencies() | |
|> Map.to_list() | |
|> Enum.sort_by(fn {_, count} -> count end, :desc) | |
|> then(fn [{possible_majority, first} | [{_, second} | _]] -> | |
cond do | |
first == second -> | |
nums | |
|> Enum.group_by(&(rem(&1, 2) == 0)) | |
|> then(fn %{false: odds, true: evens} -> | |
cond do | |
length(odds) > length(evens) -> "Majority odds" | |
length(odds) > length(evens) -> "Majority evens" | |
true -> "No majority" | |
end | |
end) | |
true -> | |
Integer.to_string(possible_majority) | |
end | |
end) | |
end | |
end |
defmodule RWC_331 do | |
@moduledoc """ | |
Write a function that determines if an array of numbers is a bitonic sequence. | |
A bitonic sequence is a sequence of numbers in which the numbers are in | |
increasing order, and after a certain point, they start decreasing. | |
Extra credit: print the peak number in the sequence! | |
iex> RWC_331.is_bitonic([1,2,3,2]) | |
3 # true, extra credit: 3 | |
iex> RWC_331.is_bitonic([1,2,3]) | |
false | |
iex> RWC_331.is_bitonic([3,4,5,5,5,2,1]) | |
5 # true, extra credit: 5 | |
""" | |
def is_bitonic(list) do | |
list | |
|> Enum.reduce_while({Enum.at(list, 0), :asc}, fn num, {peak, trend} -> | |
cond do | |
num >= peak and trend == :asc -> {:cont, {num, :asc}} | |
num < peak and trend == :asc -> {:cont, {peak, :desc}} | |
num < peak and trend == :desc -> {:cont, {peak, :desc}} | |
true -> {:halt, {peak, :err}} | |
end | |
end) | |
|> then(fn | |
{_, :err} -> false | |
{_, :asc} -> false | |
{peak, :desc} -> peak | |
end) | |
end | |
end |
defmodule RWC_332 do | |
@moduledoc """ | |
You have some gifts you want to return. Gifts bought in December have a | |
90-day return window, and all other gifts have a 30-day return window. | |
Given a gift's buy date, write a function that prints the last day you | |
can return the gift. You can choose how dates should be formatted! | |
# Given date: "Dec 25, 2023" | |
iex> RWC_332.return_gift("2023-12-25") | |
"2024-03-23" # 90 days | |
iex> RWC_332.return_gift("2023-11-25") | |
"2023-12-24" # 30 days | |
""" | |
def return_gift(date) do | |
date | |
|> String.split("-") | |
|> case do | |
# December | |
[_, "12", _] -> 90 - 1 | |
_ -> 30 - 1 | |
end | |
|> then(fn days -> | |
date | |
|> Date.from_iso8601!() | |
|> Date.add(days) | |
|> Date.to_iso8601() | |
end) | |
end | |
end |
defmodule RWC_333 do | |
@moduledoc """ | |
Write a program that prints Happy new year! without using the | |
string/character literals for the characters in the string! | |
iex> RWC_333.wish_happy_new_year() | |
"Happy New Year" | |
""" | |
def wish_happy_new_year() do | |
# Charlist | |
[72, 97, 112, 112, 121, 32, 78, 101, 119, 32, 89, 101, 97, 114] | |
|> to_string() | |
end | |
end |
defmodule RWC_334 do | |
@moduledoc """ | |
You have an array of letters. Return the number of possible sequences of | |
letters you can make using the letters in the array. | |
Extra credit: print the sequences! | |
iex> RWC_334.letters(["X"]) | |
1 | |
iex> RWC_334.letters(["A", "A", "B"]) | |
8 # "A", "B", "AA", "AB", "BA", "AAB", "ABA", "BAA" | |
""" | |
def permutations([]), do: [[]] | |
def permutations(char_list), | |
do: for(char <- char_list, rest <- permutations(char_list -- [char]), do: [char | rest]) | |
def letters(char_list) do | |
1..length(char_list) | |
|> Enum.flat_map(fn chunk_len -> | |
char_list | |
|> Enum.chunk_every(chunk_len, 1) | |
|> Enum.flat_map(fn chunk -> | |
chunk | |
|> permutations() | |
|> Enum.map(&Enum.join/1) | |
end) | |
end) | |
|> Enum.uniq() | |
|> Enum.count() | |
end | |
end |
defmodule RWC_335 do | |
@moduledoc """ | |
Given a 2D array, write a function that flips it vertically or horizontally. | |
iex> array = [ | |
...> [1,2,3], | |
...> [4,5,6], | |
...> [7,8,9] | |
...> ] | |
iex> RWC_335.flip(array, "horizontal") | |
[[3,2,1],[6,5,4],[9,8,7]] | |
iex> RWC_335.flip(array, "vertical") | |
[[7,8,9],[4,5,6],[1,2,3]] | |
""" | |
def flip(lists, "horizontal"), | |
do: | |
lists | |
|> Enum.zip_with(&Function.identity/1) | |
|> Enum.zip_with(&Enum.reverse/1) | |
def flip(lists, "vertical"), | |
do: | |
lists | |
|> Enum.zip_with(&Enum.reverse/1) | |
|> Enum.zip_with(&Function.identity/1) | |
end |
defmodule RWC_360 do | |
@moduledoc """ | |
Write a function that takes an array of integers representing the number of | |
flowers planted in a line, and an integer k representing the number of | |
additional flowers you want to plant. Return whether it's possible to plant | |
all k flowers without planting any two flowers adjacent to each other. | |
iex> RWC_360.can_plant_flowers([1, 0, 0, 0, 1], 1) | |
true # you can plant 1 flower between the others | |
iex> RWC_360.can_plant_flowers([1, 0, 0, 0, 1], 2) | |
false | |
iex> RWC_360.can_plant_flowers([0, 0, 0, 0, 0], 3) | |
true | |
iex> RWC_360.can_plant_flowers([1, 0, 1, 0, 1], 1) | |
false | |
iex> RWC_360.can_plant_flowers([1, 0, 0, 0, 1, 0, 1], 1) | |
true | |
iex> RWC_360.can_plant_flowers([1, 0, 0, 0, 0, 1, 0, 1], 2) | |
false | |
iex> RWC_360.can_plant_flowers([1, 0, 0, 0, 0, 0, 1, 0, 1], 2) | |
true | |
""" | |
def can_plant_flowers(flowers, count) do | |
flowers | |
|> then(fn flowers -> | |
flowers | |
|> pad_ones() | |
|> Enum.reverse() | |
|> pad_ones() | |
|> Enum.reverse() | |
end) | |
|> Enum.chunk_by(&(&1 == 1)) | |
|> Enum.filter(&Enum.all?(&1, fn x -> x == 0 end)) | |
|> Enum.map(fn zeros_list -> | |
zeros_list | |
|> Enum.chunk_every(3, 2, :discard) | |
|> Enum.count(&(&1 == [0, 0, 0])) | |
|> then(&(&1 >= count)) | |
end) | |
|> Enum.any?(& &1) | |
end | |
defp pad_ones(flowers) do | |
flowers | |
|> Enum.take(2) | |
|> case do | |
[0, 0] -> | |
[0 | flowers] | |
_ -> | |
flowers | |
end | |
end | |
end |
defmodule RWC_361 do | |
@moduledoc """ | |
Given an integer array nums, return the length of the longest | |
increasing subsequence. | |
iex> RWC_361.increasing_subsequence([10, 9, 2, 3, 7, 101, 18]) | |
4 | |
iex> RWC_361.increasing_subsequence([4, 4, 4, 4, 3]) | |
1 | |
""" | |
def increasing_subsequence(input) do | |
input | |
|> Enum.chunk_every(2, 1, :discard) | |
|> Enum.map(fn [a, b] -> a < b end) | |
|> Enum.chunk_by(& &1) | |
|> Enum.flat_map(fn | |
[true | _] = sub -> [length(sub)] | |
_ -> [] | |
end) | |
|> Enum.max(&>=/2, fn -> 0 end) | |
|> then(&(&1 + 1)) | |
end | |
end |
defmodule RWC_364 do | |
@moduledoc """ | |
Create a function that should take one argument n, which is a | |
positive integer. The function should return the sum of all | |
squared positive integers between 1 and n, inclusive. | |
iex> RWC_364.squares(5) | |
55 | |
iex> RWC_364.squares(10) | |
385 | |
iex> RWC_364.squares(25) | |
5525 | |
iex> RWC_364.squares(100) | |
338350 | |
""" | |
def squares(num, sum \\ 0) | |
def squares(0, sum), do: sum | |
def squares(num, sum), do: squares(num - 1, sum + num * num) | |
end |
defmodule RWC_386 do | |
@moduledoc """ | |
Write a function that generates all possible permutations of a given string. | |
iex> RWC_386.permute("abc") | |
["abc", "acb", "bac", "bca", "cab", "cba"] | |
""" | |
def get_permutations([]), do: [[]] | |
def get_permutations(list), | |
do: for(el <- list, rest <- get_permutations(list -- [el]), do: [el | rest]) | |
def permute(input) do | |
input | |
|> String.graphemes() | |
|> get_permutations() | |
|> Enum.map(&Enum.join/1) | |
end | |
end |
defmodule RWC_389 do | |
@moduledoc """ | |
Given two strings, s and p, return an array of all the start indices of p's anagrams in s. | |
iex> RWC_389.find_anagrams("cbaebabacd", "abc") | |
[0, 6] | |
iex> RWC_389.find_anagrams("fish", "cake") | |
[] | |
iex> RWC_389.find_anagrams("abab", "ab") | |
[0, 1, 2] | |
""" | |
def find_anagrams(s, p) do | |
p_sorted = p |> String.graphemes() |> Enum.sort() | |
s | |
|> String.graphemes() | |
|> Enum.chunk_every(String.length(p), 1, :discard) | |
|> Enum.map(&Enum.sort/1) | |
|> Enum.with_index() | |
|> Enum.flat_map(fn | |
{^p_sorted, i} -> [i] | |
_ -> [] | |
end) | |
end | |
end |
defmodule RWC_390 do | |
@moduledoc """ | |
Write a function that evaluates a postfix expression (also known as | |
Reverse Polish Notation) and returns the result. The expression will | |
contain single-digit integers and the operators +, -, *, and /. | |
You can assume the input is always a valid expression! | |
iex> RWC_390.evaluate_postfix("12+") | |
3 | |
iex> RWC_390.evaluate_postfix("56+7*") | |
77 | |
""" | |
@op %{ | |
"+" => &Kernel.+/2, | |
"-" => &Kernel.-/2, | |
"*" => &Kernel.*/2, | |
"/" => &div/2 | |
} | |
def evaluate_postfix(input) do | |
input | |
|> String.graphemes() | |
|> Enum.reduce({}, fn | |
el, {} -> | |
{String.to_integer(el)} | |
el, {num} when el not in ["+", "-", "/", "*"] -> | |
{num, String.to_integer(el)} | |
el, {first, second} -> | |
{@op[el].(first, second)} | |
end) | |
|> elem(0) | |
end | |
end |