Perfect shuffle: Difference between revisions

(→‎{{header|Haskell}}: Changed to more idiomatic solution)
Line 576:
1024 : 10
10000 : 300</pre>
 
=={{header|JavaScript}}==
===ES6===
<lang JavaScript>(() => {
'use strict';
 
// 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
let justifyRight = (n, cFiller, strText) =>
n > strText.length ? (
(replicateS(n, cFiller) + strText)
.slice(-n)
) : strText;
 
// TEST
const cols = transpose([
['Deck', 'Shuffles']
].concat(
[8, 24, 52, 100, 1020, 1024, 10000]
.map(x => [x.toString(), firstCycle(shuffle, range(1, x))
.all.length.toString()
])));
 
return transpose(cols.map(col => {
const width = length(maximumBy(length, col)) + 2;
return col.map(x => justifyRight(width, ' ', x));
})).map(row => row.join(' ')).join('\n');
})();</lang>
 
{{Out}}
<pre> Deck Shuffles
8 3
24 11
52 8
100 30
1020 1018
1024 10
10000 300</pre>
 
=={{header|Lua}}==
9,655

edits