Last active
September 5, 2019 18:36
-
-
Save denim2x/713f9f46c9e9ec72679a97d2135a58f9 to your computer and use it in GitHub Desktop.
JavaScript code golfing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Given a string, print the count of vowels in it. | |
* To add a minor complication, y should be counted as half (0.5) a vowel. | |
*/ | |
const Vowel = new Set('aeiou'), array = Array.from(input.toLowerCase()); | |
let y = 0; | |
const vowels = array.filter((c) => { | |
y += (c == 'y'); | |
return Vowel.has(c) | |
}); | |
print(vowels.length + y/2); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Given a string `str`, print the minimum number of character deletions such that | |
* all same-character subsequences are reduced to a single character. | |
*/ | |
let ret = 0; | |
str.replace(/(.)\1+/g, (s) => { | |
ret += s.length - 1; | |
}); | |
print(ret); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Given two string `a` and `b` as input, print the minimum number of character deletions | |
* across both strings, in order to make each of them the other's anagram. | |
* | |
* Sample input: | |
* fcrxzwscanmligyxyvym | |
* jxwtrhvujlmrpdoqbisbwhmgpmeoke | |
* | |
* Sample output: | |
* 30 | |
*/ | |
function anagram_dels(a, b) { | |
const x = new MultiSet(a); | |
return x.sim_diff(b).size; | |
} | |
class MultiSet { | |
constructor(src) { | |
if (src instanceof MultiSet) { | |
this._data = new Map(src._data); | |
} else { | |
this._data = new Map; | |
this._union(src); | |
} | |
} | |
sim_diff(other) { | |
const m = MultiSet._from(other); | |
const A = this.diff(m); | |
const B = m.diff(this); | |
return A._union(B); | |
} | |
diff(other) { | |
let ret = new MultiSet(this); | |
for (let e of other) { | |
ret.delete(e); | |
} | |
return ret; | |
} | |
union(other) { | |
return new MultiSet(this)._union(other); | |
} | |
_union(other) { | |
for (let e of _iter(other)) { | |
this.add(e); | |
} | |
return this; | |
} | |
has(item) { | |
return this._data.has(item); | |
} | |
add(item) { | |
const m = this._data; | |
m.set(item, (m.get(item) || 0) + 1); | |
return this; | |
} | |
delete(item) { | |
const m = this._data; | |
if (m.has(item)) { | |
m.set(item, m.get(item) - 1); | |
if (m.get(item) == 0) { | |
m.delete(item); | |
} | |
return true; | |
} | |
return false; | |
} | |
* [Symbol.iterator]() { | |
for (let [e, n] of this._data) { | |
for (let i = 0; i < n; i++) { | |
yield e; | |
} | |
} | |
} | |
get size() { | |
let ret = 0; | |
for (let n of this._data.values()) { | |
ret += n; | |
} | |
return ret; | |
} | |
static _from(self) { | |
if (self instanceof MultiSet) | |
return self; | |
return new MultiSet(self); | |
} | |
get repr() { | |
return `{${[...this].join(' ')}}`; | |
} | |
} | |
function* _iter(self) { | |
if (self != null) { | |
yield* self; | |
} | |
} | |
print(anagram_dels(a, b)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
Print a size ascending range of Christmas trees using asterisks, ranging from size 3 to size 9, each tree separated by a blank line. | |
A size 3 tree should look like this, with a single centered asterisk for the trunk: | |
* | |
*** | |
***** | |
* | |
*/ | |
for (let n = 3; n <= 9; n++) { | |
drawTree(n); | |
print(); | |
} | |
function drawTree(n) { | |
for (let d = 0; d < n; d++) { | |
let k = n - d; | |
for (let i = 0; i < k; i++) { | |
write(' '); | |
} | |
for (let i = k; i < k + d*2 + 1; i++) { | |
write('*'); | |
} | |
print(); | |
} | |
for (let i = 0; i < n; i++) { | |
write(' '); | |
} | |
print('*'); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Given source code as input, print all its contained line and block comments, each on a separate line. | |
*/ | |
let cache = []; | |
let temp = input.replace(/\/\*[\S\s]*?\*\//gi, (c) => { | |
cache.push(c.replace(/\s*([\n\r])\s*/gi, (m, n) => n)); | |
return '\0'; | |
}).split('\0'); | |
for (let [i, part] of temp.entries()) { | |
part.replace(/\/\/.*/gi, (c) => { | |
print(c); | |
}); | |
if (i < cache.length) { | |
print(cache[i]); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Given a time span as input, print the number of minutes within that time span. | |
* The time span will be two times separated by a dash, including hour, a colon, minute, and "am" or "pm", | |
* e.g.: 12:01am-11:59pm. All spans are moving forward in time. | |
*/ | |
const times = /^\s*(\d+)\s*:\s*(\d+)\s*(am|pm)\s*-\s*(\d+)\s*:\s*(\d+)\s*(am|pm)\s*$/.exec(input); | |
const int = parseInt; | |
const A = time_at(0); | |
const B = time_at(1); | |
if (A.t == B.t) { | |
print(B.mins - A.mins); | |
} else if (A.t != B.t) { | |
print(B.Mins - A.mins); | |
} | |
function time_at(i) { | |
let k = 3*i; | |
return { h: int(times[k + 1]), m: int(times[k + 2]), t: times[k + 3] == 'am', | |
get H() { return this.h + 12 }, | |
get mins() { return this.h*60 + this.m }, | |
get Mins() { return this.H*60 + this.m } | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Given a string `input` comprised of n sentences (preceded by n) and t words (preceded by t), print | |
* on separate lines the count of each word within all sentences. | |
*/ | |
const int = parseInt; | |
let array = input.split(/\s*[\n\r]+\s*/g); | |
let n = int(array[0]); | |
let S = array.slice(1, n+1); | |
let t = int(array[n+1]); | |
let W = new Map(array.slice(n+2, t + n+2).map(w => [w, 0])); | |
let s = S.join(' '); | |
s.replace(/[a-z1-9_]+/gi, (w) => { | |
if (W.has(w)) { | |
W.set(w, W.get(w) + 1); | |
} | |
}); | |
for (let n of W.values()) { | |
print(n); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A number is a divisor of another number if it can divide into it with no remainder. | |
* Print the positive divisors of each number from 1 to 100 inclusive, on their own line, | |
* with each divisor separated by a space. | |
*/ | |
for (let i = 1; i <= 100; i++) { | |
print(getDivisors(i, ' ')); | |
} | |
function getDivisors(n, sep) { | |
let ret = [1]; | |
for (let d = 2; d <= n/2; d++) { | |
if (n % d == 0) { | |
ret.push(d); | |
} | |
} | |
n > 1 && ret.push(n); | |
return sep != null ? ret.join(sep) : ret; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Given a block of text as input, print all domain names found within the text, sorted | |
* and separated by ';'. | |
*/ | |
let cache = new Set; | |
input.replace(/\bhttps?:\/\/(?:ww[w2]\.)?([^\/\s\?"\\']+(?:\.[^\/\s\?"\\']+)+)/gi, (e, d) => { | |
cache.add(d); | |
}); | |
print(Array.from(cache).sort().join(';')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Given a block of text as input, print all unique e-mail adrresses found within the text, sorted | |
* and separated by ';'. | |
*/ | |
let cache = new Set; | |
input.replace(/\b[^@\s]+@[^@\s]+\.[a-z]{1,3}\b/gi, (e) => { | |
cache.add(e); | |
}); | |
print(Array.from(cache).sort().join(';')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Given a word as input, print true of the word is a palindrome, or false otherwise. | |
*/ | |
print(input == Array.from(input).reverse().join('')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Function.prototype.partial = function (...args) { | |
return this.bind(null, ...args); | |
}; | |
const suits = [ | |
['🂱 🂲 🂳 🂴 🂵 🂶 🂷 🂸 🂹 🂺', '🂻 🂼 🂽 🂾'], | |
['🂡 🂢 🂣 🂤 🂥 🂦 🂧 🂨 🂩 🂪', '🂫 🂬 🂭 🂮'], | |
['🃁 🃂 🃃 🃄 🃅 🃆 🃇 🃈 🃉 🃊', '🃋 🃌 🃍 🃎'], | |
['🃑 🃒 🃓 🃔 🃕 🃖 🃗 🃘 🃙 🃚', '🃛 🃜 🃝 🃞'], | |
]; | |
const model = suits.map(([low, high]) => { | |
let A; | |
[A, ...low] = low.split(' '); | |
high = [...high.split(' '), A]; | |
let cards = new Map([...low, ...high].map((e, i) => [e, 2+i])); | |
cards.high = new Map(high.map((e, i) => [11+i, 'JCQKA'[i]])); | |
return cards; | |
}); | |
function royal_flush(hand) { | |
for (let temp of hand) { | |
if (temp.includes()) | |
continue; | |
temp.sort(numeric); | |
return temp.every((e, i) => e == i + 10); | |
} | |
return false; | |
} | |
function straight_flush(hand) { | |
for (let temp of hand) { | |
if (temp.includes()) | |
continue; | |
temp.sort(numeric); | |
return temp.every(sequenced); | |
} | |
return false; | |
} | |
var four_alike = _alike.partial(4); | |
var full_house = freq_match.partial('2,3'); | |
function flush(hand) { | |
for (let temp of hand) { | |
if (temp.includes()) | |
continue; | |
return true; | |
} | |
return false; | |
} | |
function straight(hand) { | |
let cache = []; | |
for (let i = 0; i < hand.count; i++) { | |
cache.push(hand.find(e => e[i])[i]); | |
} | |
cache.sort(numeric); | |
return cache.every(sequenced); | |
} | |
var three_alike = _alike.partial(3); | |
var two_pair = freq_match.partial('1,2,2'); | |
var pair = _alike.partial(2); | |
for (let hand of arguments) { | |
[, ...hand] = hand.match(/^(..)(..)(..)(..)(..)$/); | |
switch (true) { | |
case royal_flush(res()): | |
print('Royal Flush'); | |
break; | |
case straight_flush(res()): | |
print('Straight Flush'); | |
break; | |
case four_alike(res()): | |
print('Four of a Kind'); | |
break; | |
case full_house(res()): | |
print('Full House'); | |
break; | |
case flush(res()): | |
print('Flush'); | |
break; | |
case straight(res()): | |
print('Straight'); | |
break; | |
case three_alike(res()): | |
print('Three of a Kind'); | |
break; | |
case two_pair(res()): | |
print('Two Pair'); | |
break; | |
case pair(res()): | |
print('Pair'); | |
break; | |
default: | |
print('High Card'); | |
} | |
function res() { | |
let ret = model.map(suit => { | |
let ret = hand.map(c => suit.get(c)); | |
ret.high = suit.high; | |
return ret; | |
}); | |
ret.count = hand.length; | |
return ret; | |
} | |
} | |
function _alike(count, hand) { | |
let freq = new Map; | |
for (let i = 0; i < hand.count; i++) { | |
let c = hand.find(e => e[i])[i]; | |
freq.set(c, (freq.get(c) || 0) + 1); | |
if (freq.get(c) == count) | |
return true; | |
} | |
return false; | |
} | |
function freq_match(pat, hand) { | |
let freq = new Map; | |
for (let i = 0; i < hand.count; i++) { | |
let c = hand.find(e => e[i])[i]; | |
freq.set(c, (freq.get(c) || 0) + 1); | |
} | |
let vals = [...freq.values()]; | |
return vals.sort(numeric).join() == pat; | |
} | |
function sequenced(e, i, a) { | |
return e == a[0] + i; | |
} | |
function numeric(a, b) { | |
return a - b; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Given input with a number between 0 and 99 in English, print the integer equal to the number. | |
*/ | |
let output; | |
const r = String.raw; | |
let units_a = _`one two three four five`; | |
let units_b = _`six seven eight nine`; | |
let units_c = units_b.replace('eight', 'eigh'); | |
let tens_a = _`thir four fif`; | |
let tens_b = tens_a.replace('four', 'for'); | |
let unit = r`${units_a}|${units_b}`; | |
let _teen = r`${_`ten eleven twelve`}|(?:${tens_a}|${units_c})teen`; | |
let _ty_ = r`(?:(?:(twen)|${tens_b}|${units_c})ty)?\s*(?:${unit})?`; | |
if (input == 'zero') { | |
output = 0; | |
} else { | |
let m = RE(_teen); | |
if (m) { | |
output = 10 + m.findIndex(Boolean); | |
} else { | |
m = RE(_ty_); | |
if (m) { | |
let tens = m.slice(0, 8).findIndex(Boolean); | |
let units = m.slice(8).findIndex(Boolean); | |
output = 0; | |
if (tens >= 0) { | |
output = 10 * (2 + tens); | |
} | |
output += 1 + units; | |
} else { | |
output = NaN; | |
} | |
} | |
} | |
function RE(pat) { | |
let re = new RegExp(r`^(?:${pat})$`, 'i'); | |
let m = re.exec(input.trim()); | |
return m ? m.slice(1) : null; | |
} | |
function _([s]) { | |
return s.split(/\s+/g).map(e => `(${e})`).join('|'); | |
} | |
print(output); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Given a list of pairs (in arguments), print on separate lines the relationship between each pair's components. | |
* | |
* ✂ cuts 📄 covers 💎 crushes 🦎 poisons 🖖 smashes ✂ decapitates 🦎 eats 📄 disproves 🖖 vaporizes 💎 crushes ✂. | |
*/ | |
const model = { | |
Rock: { Lizard: 'crushes', Scissors: 'crushes', $: '💎' }, | |
Paper: { Rock: 'covers', Spock: 'disproves', $: '📄' }, | |
Scissors: { Paper: 'cuts', Lizard: 'decapitates', $: '✂' }, | |
Spock: { Scissors: 'smashes', Rock: 'vaporizes', $: '🖖' }, | |
Lizard: { Spock: 'poisons', Paper: 'eats', $: '🦎' }, | |
}; | |
const chars = new Map; | |
for (let [a, { $: c }] of Object.entries(model)) { | |
chars.set(a, c); | |
} | |
const rels = new Map; | |
for (let [k, B] of Object.entries(model)) { | |
let a = chars.get(k); | |
rels.set(`${a}${a}`, 'Tie'); | |
for (let [k, r] of Object.entries(B)) { | |
let b = chars.get(k); | |
let val = `${a} ${r} ${b}`; | |
rels.set(`${a}${b}`, val); | |
rels.set(`${b}${a}`, val); | |
} | |
} | |
for (let pair of arguments) { | |
print(rels.get(pair)); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Given an integer (0-99) as input, print it's spelling in English | |
*/ | |
let output; | |
const tens_a = `thir four fif`; | |
const tens_b = tens_a.replace('four', 'for'); | |
const words_b = 'six seven eight nine'); | |
const words_c = words_b.replace('eight', 'eigh')); | |
const words = _`zero one two three four five ${words_b} ten eleven twelve`; | |
const words_teen = _`${tens_a} ${words_c}`; | |
const words_ty = _`twen ${tens_b} ${words_c}`; | |
if (0 <= input && input <= 99) { | |
let tens = Math.floor(input / 10); | |
let units = input % 10; | |
if (input > 19) { | |
output = `${words_ty[tens-2]}ty`; | |
if (units > 0) { | |
output = `${output} ${words[units]}`; | |
} | |
} else if (input > 12) { | |
output = `${words_teen[input-13]}teen`; | |
} else { | |
output = words[input]; | |
} | |
} | |
function _([s]) { | |
return s.split(/\s+/g); | |
} | |
print(output); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// For three given arrays A, B, C, find the triplet A[i], B[j], C[k] such that A[i] < B[j] < C[k] | |
let res; | |
for (let i = 0; i < A.length && !res; i++) { | |
for (let j = 0; j < B.length && !res; j++) { | |
for (let k = 0; k < C.length; k++) { | |
if (A[i] < B[j] && B[j] < C[k]) { | |
res = [i, j, k]; | |
break; | |
} | |
} | |
} | |
} | |
print(...res); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Given a `grid` of letters and a list of `words`, print the starting (1-indexed) position for each | |
* of these words within the grid, along all eight directions. | |
* | |
* Sample `grid`: | |
* abcDEFGhigg | |
* hEbkWalDork | |
* FtyAwaldORm | |
* FtsimrLqsrc | |
* byoArBeDeyv | |
* Klcbqwikomk | |
* strEBGadhrb | |
* yUiqlxcnBjf | |
* | |
* Sample `words`: | |
* Waldorf | |
* Bambi | |
* Betty | |
* Dagbert | |
* | |
* Output: | |
* 2 5 | |
* 2 3 | |
* 1 2 | |
* 7 8 | |
*/ | |
function* search(grid, words) { | |
const fwd = new Map, rev = new Map; | |
for (let w of words) { | |
fwd.set(w, new Cache(w)); | |
rev.set(w, new Cache(w, true)); | |
} | |
for (let y = 0; y < grid.length; y++) { | |
let row = grid[y]; | |
for (let x = 0; x < row.length; x++) { | |
let c = row[x]; | |
for (let [w, cache] of fwd) { | |
cache.add(c, x, y); | |
} | |
for (let [w, cache] of rev) { | |
cache.add(c, x, y); | |
} | |
} | |
} | |
for (let w of words) { | |
yield fwd.get(w).match || rev.get(w).match; | |
} | |
} | |
class Cache { | |
constructor(word, reversed=false) { | |
this._word = word.toLowerCase(); | |
this._reversed = reversed; | |
if (this._reversed) { | |
this._word = reverse(this._word); | |
} | |
this._vectors = []; | |
this._matches = []; | |
} | |
add(char, x, y) { | |
if (this.match) | |
return false; | |
let c = char.toLowerCase(), ok = false; | |
let cell = new Cell(x, y); | |
for (let v of this._vectors) { | |
let k = v.length; | |
let end = v[k-1]; | |
if (v.dir && !v.dir.same_direction(end, cell)) | |
continue; | |
if (this._word[k] != c) | |
continue; | |
v.dir = end.direction(cell); | |
if (v.dir == null) | |
continue; | |
ok = k == 1 ? [end] : (ok || true); | |
v.push(cell); | |
if (v.length == this._word.length) { | |
this._matches.push(this._reversed ? cell : v[0]); | |
} | |
} | |
if (Array.isArray(ok)) { | |
this._vectors.push(ok); | |
} else if (!ok && this._word[0] == c) { | |
this._vectors.push([cell]); | |
} | |
return true; | |
} | |
* [Symbol.iterator]() { | |
yield* this._matches; | |
} | |
get match() { | |
return this._matches[0]; | |
} | |
get size() { | |
return this._matches.length; | |
} | |
} | |
class Cell { | |
constructor(x, y) { | |
this._x = x; | |
this._y = y; | |
} | |
direction(dest) { | |
let ret = dest.sub(this); | |
let { x, y } = ret; | |
if (x == 1 && y == 0) | |
return ret; | |
if (Math.abs(x) <= 1 && y == 1) | |
return ret; | |
} | |
sub({ x, y }) { | |
return new Cell(this.x - x, this.y - y); | |
} | |
same_direction(a, b) { | |
// 'this' is the direction | |
return this.equals(a.direction(b)); | |
} | |
equals(other) { | |
if (other == null) | |
return false; | |
return this.x == other.x && this.y == other.y; | |
} | |
get x() { | |
return this._x; | |
} | |
get y() { | |
return this._y; | |
} | |
get repr() { | |
return `(${this.x}, ${this.y})`; | |
} | |
} | |
function reverse(str) { | |
return Array.from(str).reverse().join(''); | |
} | |
for (let {x, y} of search(grid, words)) { | |
print(y + 1, x + 1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment