Skip to content

Instantly share code, notes, and snippets.

@jda0
Last active August 4, 2020 16:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jda0/01070831825ed63efcd1f626653a16a3 to your computer and use it in GitHub Desktop.
Save jda0/01070831825ed63efcd1f626653a16a3 to your computer and use it in GitHub Desktop.
/**
* Calculates Hamming weight of a positive integer.
* The Hamming weight of an integer can be calculated by seeing if the last bit is set, then shifting the number
* down by one bit, and doing likewise until the number is zero then returning the bitcount.
* @param {number} n
* @returns {number} Hamming weight
*/
H = n => n ? (n & 1) + H(n>>1) : 0
let alternateChars;
/**
*
* @param {string} a
* @returns {string}
*/
alternateChars = a =>
[].reduce.call(a, ([r, s], x) => // reducing over the input string
(
/[a-z]/i.test(x)
? (
/[aeiou]/i.test(x) === /[aeiou]/i.test(s) // if a vowel or consonant is followed by like
? (s < x ? (s = x) : 1) // consume the letter with greater unicode value
: ((r += s) || 1) && (s = x) // else consume the next letter
// and output the previously consumed codepoint
)
: (r += x) || 1 // consume if not alphanumeric and continue
) && [r, s], // continue reduction with consumption and pending output
['', ''] // starting with each empty
).join('') // then append the last consumption to the output.
/**
* `SortNode` is a sorted linked list with `insert` and `flat` methods.
* @class
* @constructor
* @param {*} value
*/
function SortNode (value) {
this.value = value;
return this;
}
/**
* Compares a `SortNode` to a value.
* @memberof SortNode
* @this SortNode
* @param {*} value
* @returns {number}
*/
SortNode.prototype.compare = function (value) {
return typeof this.value === 'string'
? this.value.localeCompare(value)
: typeof value === 'string'
? -value.localeCompare(this.value)
: this.value - value;
}
/**
* Inserts a value into the linked list containing `SortNode`.
* @memberof SortNode
* @this SortNode
* @param {*} value
* @returns {SortNode} A `SortNode` containing the inserted value.
*
SortNode.prototype.insert = function (value) {
if (this.value === undefined) {
this.value = value;
return this;
}
if (this.prev && this.prev.compare(value) > 0) {
return this.prev.insert(value);
}
if (this.next && this.next.compare(value) <= 0) {
return this.next.insert(value);
}
if (this.compare(value) > 0) {
const prev = new SortNode(value);
prev.prev = this.prev;
if (this.prev) {
this.prev.next = prev;
}
prev.next = this;
return this.prev = prev;
} else {
const next = new SortNode(value);
next.next = this.next;
if (this.next) {
this.next.prev = next;
}
next.prev = this;
return this.next = next;
}
}
/**
* Flattens the linked list containing `SortNode` to an array of values.
* @memberof SortNode
* @this SortNode
* @param {number} dir [INTERNAL] Used to recursively flatten the list from linked nodes.
* @returns {*[]}
SortNode.prototype.flat = function (dir) {
return [
...(this.prev && dir !== +1 ? this.prev.flat(-1) : []),
this.value,
...(this.next && dir !== -1 ? this.next.flat(+1) : []),
]
}
let f, c, d, g, i;
/**
* Note: this will pollute global scope.
* Accepts a floating point number and returns a fractional representation of `n`
* in the form `[numerator, denominator]`.
* If you encounter a stack overflow, try increasing the value of `e`,
* i.e. do not set `e` to `Number.EPSILON`.
* @param {number} n a floating point number
* @param {number?} e epsilon
* @returns {[number, number]} a fractional representation of `n`
*/
f = (n, e = 1e-3) =>
(
c = (
g = (n, e, c = []) => // `g` is a lambda that builds a continued fractional
// representation of an `n`:
(d = n - (i = ~~n)) > e // if the fractional component of the number passed to `g`
// is greater than the epsilon
? [...c, i, ...g(1 / d, e, c)] // ...append the natural component of `n`, and the result
// of recursively calling `g` on the inverse of the
// fractional component (e.g.
// `g(3.5, e, [1]) == g(1 / 0.5, e, [1, 3])`)
: [...c, i] // ...else append `n` and return the generated continued
// fraction.
)(n, e).reverse() // call `g` with our initial arguments and reverse
// the result.
).reduce( // then, reduce our RTL continued fraction into a standard
// fractional form of `n`:
([d, n], a) => [a * d + n, d], // by recursively reducing `1 / [a + n / d]` into the
// equivalent `d / [a * d + n]` (e.g.
// 1 / [2 + 3 / 4] == 4 / [2 * 4 + 3] == 4 / 11)
[c.shift(), 1] // starting with the smallest component of the
// continued fraction and working outwards
) // leaving us with a fractional representation of `n`.
let f, c, q;
/**
* Note: this will pollute global scope.
* Accepts a string and returns a list of valid formable IPv4 addresses.
* @example f('127001') ~> ['12.70.0.1', '127.0.0.1']
*
* @param {string} s A string representation of IPv4 address (digits only)
* @param {number} d [INTERNAL] Recursion depth / group count - 1
* @param {string} p [INTERNAL]
* @param {string[]} r [INTERNAL] Results array
* @returns {string[]}
*/
f = (s, d = 3, p = '', r = []) =>
[1,2,3].map(n => // Take each number 1 to 3 in turn (`n`).
d // If we have more groups to form...
? (
(
c = s => // We check groups by
s && // checking that they're not empty,
(
!s[1] || // that they don't contain a zero prefixing
s[0] != '0' // another digit (e.g. '02')
) &&
+s < 256 // and that they have a value less than 256.
)(
q = s.slice(0, n) // Check the next `n` characters (our next
) && // potential group) and if it's OK,
f( // recursively create groups from
s.slice(n), // what's left over,
d - 1,
d == 3 // joining our new group to what we had
? q // already and making sure we don't prepend
: p + '.' + q, // the entire IP address with a period.
r
)
)
: ( // If we don't have any more groups to form,
s.length == n && // we have exactly enough characters left to
c(s) && // form a group and the final group is OK,
r.push(p + '.' + s) // push our result to our results array
)
) &&
r // and return the results array when we're done.
let f,g,h;
/**
* Shoutout to Nick. If you see this, I hope this formatting doesn't "hurt your
* soul" quite as much as last week's.
*/
/**
* Note: this will pollute global scope.
* Accepts an array of strings and sorts them by ascending number of
* distinct characters, tie-breaking by descending string length.
* @example f(['Bananas', 'do', 'not', 'grow', 'in', 'Mississippi'])
* ~> ['do', 'in', 'not', 'Mississippi', 'Bananas', 'grow']
*
* @param {string} x An array of strings to sort
* @returns {string[]}
*/
f = x =>
x.sort((a, b) => // First, we sort by length
(h = x => x.length)(b) - // descending (b - a ~> desc.).
h(a) // `Array.prototype.length` is
// hereby aliased to `h`.
).sort((a, b) => // Then, we sort by distinct
h(( // characters by comparing the
g = x => [].reduce.call( // lengths of the strings once
x, // we've removed all
(a,b) => a.includes(b) ? a : a + b // duplicates (`g`) — if they're
) // equal, the original order
)(a)) - // (which is determined by the
h(g(b)) // previous sort) breaks ties.
)
let f,g;
/**
* Note: this will pollute global scope.
* Accepts an array of strings and sorts them by ascending number of
* distinct characters, tie-breaking by descending string length.
* @example f(['Bananas', 'do', 'not', 'grow', 'in', 'Mississippi'])
* ~> ['do', 'in', 'not', 'Mississippi', 'Bananas', 'grow']
*
* @param {string} x An array of strings to sort
* @returns {string[]}
*/
f = x =>
x.sort((a, b) => // Then, we sort by distinct
( // characters by comparing the
g = x => new Set(x).size // lengths of the strings
)(a) - // once we've removed all
g(b) || // duplicates (`g`) — if they're
( // characters by comparing the
g = x => x.length // lengths of the strings
)(b) - // once we've removed all
g(a) // equal, comparing the length
) // of the string breaks ties.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment