Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
122
Task/Perfect-shuffle/JavaScript/perfect-shuffle.js
Normal file
122
Task/Perfect-shuffle/JavaScript/perfect-shuffle.js
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
(() => {
|
||||
'use strict';
|
||||
|
||||
// shuffleCycleLength :: Int -> Int
|
||||
const shuffleCycleLength = deckSize =>
|
||||
firstCycle(shuffle, range(1, deckSize))
|
||||
.all.length;
|
||||
|
||||
// shuffle :: [a] -> [a]
|
||||
const shuffle = xs =>
|
||||
concat(zip.apply(null, splitAt(div(length(xs), 2), xs)));
|
||||
|
||||
// firstycle :: Eq a => (a -> a) -> a -> [a]
|
||||
const firstCycle = (f, x) =>
|
||||
until(
|
||||
m => EqArray(x, m.current),
|
||||
m => {
|
||||
const fx = f(m.current);
|
||||
return {
|
||||
current: fx,
|
||||
all: m.all.concat([fx])
|
||||
};
|
||||
}, {
|
||||
current: f(x),
|
||||
all: [x]
|
||||
}
|
||||
);
|
||||
|
||||
// Two arrays equal ?
|
||||
// EqArray :: [a] -> [b] -> Bool
|
||||
const EqArray = (xs, ys) => {
|
||||
const [nx, ny] = [xs.length, ys.length];
|
||||
return nx === ny ? (
|
||||
nx > 0 ? (
|
||||
xs[0] === ys[0] && EqArray(xs.slice(1), ys.slice(1))
|
||||
) : true
|
||||
) : false;
|
||||
};
|
||||
|
||||
// GENERIC FUNCTIONS
|
||||
|
||||
// zip :: [a] -> [b] -> [(a,b)]
|
||||
const zip = (xs, ys) =>
|
||||
xs.slice(0, Math.min(xs.length, ys.length))
|
||||
.map((x, i) => [x, ys[i]]);
|
||||
|
||||
// concat :: [[a]] -> [a]
|
||||
const concat = xs => [].concat.apply([], xs);
|
||||
|
||||
// splitAt :: Int -> [a] -> ([a],[a])
|
||||
const splitAt = (n, xs) => [xs.slice(0, n), xs.slice(n)];
|
||||
|
||||
// div :: Num -> Num -> Int
|
||||
const div = (x, y) => Math.floor(x / y);
|
||||
|
||||
// until :: (a -> Bool) -> (a -> a) -> a -> a
|
||||
const until = (p, f, x) => {
|
||||
const go = x => p(x) ? x : go(f(x));
|
||||
return go(x);
|
||||
}
|
||||
|
||||
// range :: Int -> Int -> [Int]
|
||||
const range = (m, n) =>
|
||||
Array.from({
|
||||
length: Math.floor(n - m) + 1
|
||||
}, (_, i) => m + i);
|
||||
|
||||
// length :: [a] -> Int
|
||||
// length :: Text -> Int
|
||||
const length = xs => xs.length;
|
||||
|
||||
// maximumBy :: (a -> a -> Ordering) -> [a] -> a
|
||||
const maximumBy = (f, xs) =>
|
||||
xs.reduce((a, x) => a === undefined ? x : (
|
||||
f(x, a) > 0 ? x : a
|
||||
), undefined);
|
||||
|
||||
// transpose :: [[a]] -> [[a]]
|
||||
const transpose = xs =>
|
||||
xs[0].map((_, iCol) => xs.map((row) => row[iCol]));
|
||||
|
||||
// show :: a -> String
|
||||
const show = x => JSON.stringify(x, null, 2);
|
||||
|
||||
// replicateS :: Int -> String -> String
|
||||
const replicateS = (n, s) => {
|
||||
let v = s,
|
||||
o = '';
|
||||
if (n < 1) return o;
|
||||
while (n > 1) {
|
||||
if (n & 1) o = o.concat(v);
|
||||
n >>= 1;
|
||||
v = v.concat(v);
|
||||
}
|
||||
return o.concat(v);
|
||||
};
|
||||
|
||||
// justifyRight :: Int -> Char -> Text -> Text
|
||||
const justifyRight = (n, cFiller, strText) =>
|
||||
n > strText.length ? (
|
||||
(replicateS(n, cFiller) + strText)
|
||||
.slice(-n)
|
||||
) : strText;
|
||||
|
||||
// TEST
|
||||
return transpose(transpose([
|
||||
['Deck', 'Shuffles']
|
||||
].concat(
|
||||
[8, 24, 52, 100, 1020, 1024, 10000]
|
||||
.map(n => [n.toString(), shuffleCycleLength(n)
|
||||
.toString()
|
||||
])))
|
||||
.map(col => { // Right-justified number columns
|
||||
const width = length(
|
||||
maximumBy((a, b) => length(a) - length(b), col)
|
||||
) + 2;
|
||||
|
||||
return col.map(x => justifyRight(width, ' ', x));
|
||||
}))
|
||||
.map(row => row.join(''))
|
||||
.join('\n');
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue