Humble numbers: Difference between revisions
Content added Content deleted
(→{{header|C sharp|C#}}: added direct generatio logarithms version) |
(→{{header|JavaScript}}: updated primitives) |
||
Line 1,818: | Line 1,818: | ||
'use strict'; |
'use strict'; |
||
// ------------------ |
// ------------------ HUMBLE NUMBERS ------------------- |
||
// humbles :: () -> [Int] |
// humbles :: () -> [Int] |
||
Line 1,835: | Line 1,835: | ||
}; |
}; |
||
// ----------------------- |
// ----------------------- TEST ------------------------ |
||
// main :: IO () |
// main :: IO () |
||
const main = () => { |
const main = () => { |
||
Line 1,863: | Line 1,863: | ||
// -----------------GENERIC FUNCTIONS |
// ----------------- GENERIC FUNCTIONS ----------------- |
||
// chunksOf :: Int -> [a] -> [[a]] |
// chunksOf :: Int -> [a] -> [[a]] |
||
const chunksOf = n |
const chunksOf = n => |
||
enumFromThenTo(0)(n)( |
xs => enumFromThenTo(0)(n)( |
||
xs.length - 1 |
xs.length - 1 |
||
).reduce( |
).reduce( |
||
Line 1,873: | Line 1,873: | ||
[] |
[] |
||
); |
); |
||
// compose (<<<) :: (b -> c) -> (a -> b) -> a -> c |
// compose (<<<) :: (b -> c) -> (a -> b) -> a -> c |
||
const compose = (...fs) => |
const compose = (...fs) => |
||
// A function defined by the right-to-left |
|||
// composition of all the functions in fs. |
|||
⚫ | |||
(f, g) => x => f(g(x)), |
|||
x => x |
|||
⚫ | |||
// concat :: [[a]] -> [a] |
// concat :: [[a]] -> [a] |
||
Line 1,887: | Line 1,894: | ||
return unit.concat.apply(unit, xs); |
return unit.concat.apply(unit, xs); |
||
})() : []; |
})() : []; |
||
// enumFromThenTo :: Int -> Int -> Int -> [Int] |
// enumFromThenTo :: Int -> Int -> Int -> [Int] |
||
const enumFromThenTo = x1 => |
const enumFromThenTo = x1 => |
||
x2 => y => { |
|||
const d = x2 - x1; |
|||
return Array.from({ |
|||
length: Math.floor(y - x2) / d + 2 |
|||
}, (_, i) => x1 + (d * i)); |
|||
⚫ | |||
⚫ | |||
// enumFromTo :: Int -> Int -> [Int] |
// enumFromTo :: Int -> Int -> [Int] |
||
const enumFromTo = m |
const enumFromTo = m => |
||
Array.from({ |
n => Array.from({ |
||
length: 1 + n - m |
length: 1 + n - m |
||
}, (_, i) => m + i); |
}, (_, i) => m + i); |
||
// fTable :: String -> (a -> String) -> (b -> String) |
// fTable :: String -> (a -> String) -> (b -> String) |
||
Line 1,917: | Line 1,928: | ||
).join('\n'); |
).join('\n'); |
||
}; |
}; |
||
// fmapGen <$> :: (a -> b) -> Gen [a] -> Gen [b] |
// fmapGen <$> :: (a -> b) -> Gen [a] -> Gen [b] |
||
Line 1,928: | Line 1,940: | ||
}; |
}; |
||
// group :: [a] -> [[a]] |
// group :: Eq a => [a] -> [[a]] |
||
const group = xs => { |
const group = xs => { |
||
// A list of lists, each containing only equal elements, |
|||
// such that the concatenation of these lists is xs. |
|||
const go = xs => |
const go = xs => |
||
0 < xs.length ? (() => { |
0 < xs.length ? (() => { |
||
Line 1,939: | Line 1,954: | ||
) : [xs]; |
) : [xs]; |
||
})() : []; |
})() : []; |
||
const v = go(list(xs)); |
|||
return 'string' === typeof xs ? ( |
|||
v.map(x => x.join('')) |
|||
) : v; |
|||
}; |
}; |
||
// justifyRight :: Int -> Char -> String -> String |
// justifyRight :: Int -> Char -> String -> String |
||
const justifyRight = n |
const justifyRight = n => |
||
// The string s, preceded by enough padding (with |
|||
// the character c) to reach the string length n. |
|||
⚫ | |||
⚫ | |||
⚫ | |||
) : s; |
) : s; |
||
Line 1,958: | Line 1,978: | ||
) : Infinity; |
) : Infinity; |
||
⚫ | |||
// list :: StringOrArrayLike b => b -> [a] |
|||
const list = xs => |
|||
// xs itself, if it is an Array, |
|||
// or an Array derived from xs. |
|||
Array.isArray(xs) ? ( |
|||
xs |
xs |
||
) : |
) : Array.from(xs); |
||
⚫ | |||
const map = f => |
|||
// The list obtained by applying f |
|||
// to each element of xs. |
|||
// (The image of xs under f). |
|||
xs => [...xs].map(f); |
|||
// str :: a -> String |
// str :: a -> String |
||
Line 1,994: | Line 2,025: | ||
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] |
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] |
||
const zipWith = f => |
const zipWith = f => |
||
// Use of `take` and `length` here allows zipping with non-finite lists |
|||
⚫ | |||
// i.e. generators like cycle, repeat, iterate. |
|||
⚫ | |||
xs => ys => { |
|||
const n = Math.min(length(xs), length(ys)); |
|||
return |
return Infinity > n ? ( |
||
(([as, bs]) => Array.from({ |
|||
length: n |
|||
}, (_, i) => f(as[i])( |
|||
bs[i] |
|||
)))([xs, ys].map( |
|||
⚫ | |||
compose(take(n), list) |
|||
)) |
|||
) : zipWithGen(f)(xs)(ys); |
|||
}; |
|||
// MAIN --- |
// MAIN --- |