Middle three digits: Difference between revisions
Content added Content deleted
m (→version 2: changed wording in the REXX section header.) |
(→{{header|JavaScript}}: Added an option-type variant (Trans: Python)) |
||
Line 2,648: | Line 2,648: | ||
-2002: Invalid length 4 |
-2002: Invalid length 4 |
||
0: Invalid length 1</pre> |
0: Invalid length 1</pre> |
||
Or, using an option type, composing a solution from existing generic primitives, and formatting the output a little: |
|||
{{Trans|Python}} |
|||
<lang javascript>(() => { |
|||
'use strict'; |
|||
// mid3digits :: Int -> Either String String |
|||
const mid3digits = n => { |
|||
const |
|||
m = abs(n), |
|||
s = m.toString(); |
|||
return 100 > m ? ( |
|||
Left('Less than 3 digits') |
|||
) : even(length(s)) ? ( |
|||
Left('Even digit count') |
|||
) : Right(take(3, drop(quot(length(s) - 3, 2), s))); |
|||
}; |
|||
// TEST ----------------------------------------------- |
|||
const main = () => { |
|||
const |
|||
xs = [ |
|||
123, 12345, 1234567, 987654321, 10001, -10001, -123, |
|||
-100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0 |
|||
], |
|||
w = length( |
|||
maximumBy( |
|||
comparing(x => x.toString().length), |
|||
xs |
|||
).toString() |
|||
); |
|||
return ( |
|||
unlines(map( |
|||
n => justifyRight(w, ' ', n.toString()) + ' -> ' + |
|||
either( |
|||
s => '(' + s + ')', |
|||
id, |
|||
mid3digits(n) |
|||
), |
|||
xs |
|||
)) |
|||
); |
|||
}; |
|||
// GENERIC FUNCTIONS ---------------------------------- |
|||
// Left :: a -> Either a b |
|||
const Left = x => ({ |
|||
type: 'Either', |
|||
Left: x |
|||
}); |
|||
// Right :: b -> Either a b |
|||
const Right = x => ({ |
|||
type: 'Either', |
|||
Right: x |
|||
}); |
|||
// abs :: Num -> Num |
|||
const abs = Math.abs; |
|||
// comparing :: (a -> b) -> (a -> a -> Ordering) |
|||
const comparing = f => |
|||
(x, y) => { |
|||
const |
|||
a = f(x), |
|||
b = f(y); |
|||
return a < b ? -1 : (a > b ? 1 : 0); |
|||
}; |
|||
// drop :: Int -> [a] -> [a] |
|||
// drop :: Int -> Generator [a] -> Generator [a] |
|||
// drop :: Int -> String -> String |
|||
const drop = (n, xs) => |
|||
Infinity > length(xs) ? ( |
|||
xs.slice(n) |
|||
) : (take(n, xs), xs); |
|||
// either :: (a -> c) -> (b -> c) -> Either a b -> c |
|||
const either = (fl, fr, e) => |
|||
'Either' === e.type ? ( |
|||
undefined !== e.Left ? ( |
|||
fl(e.Left) |
|||
) : fr(e.Right) |
|||
) : undefined; |
|||
// even :: Int -> Bool |
|||
const even = n => 0 === n % 2; |
|||
// id :: a -> a |
|||
const id = x => x; |
|||
// justifyRight :: Int -> Char -> String -> String |
|||
const justifyRight = (n, cFiller, s) => |
|||
n > s.length ? ( |
|||
s.padStart(n, cFiller) |
|||
) : s; |
|||
// Returns Infinity over objects without finite length. |
|||
// This enables zip and zipWith to choose the shorter |
|||
// argument when one is non-finite, like cycle, repeat etc |
|||
// length :: [a] -> Int |
|||
const length = xs => |
|||
(Array.isArray(xs) || 'string' === typeof xs) ? ( |
|||
xs.length |
|||
) : Infinity; |
|||
// maximumBy :: (a -> a -> Ordering) -> [a] -> a |
|||
const maximumBy = (f, xs) => |
|||
0 < xs.length ? ( |
|||
xs.slice(1) |
|||
.reduce((a, x) => 0 < f(x, a) ? x : a, xs[0]) |
|||
) : undefined; |
|||
// map :: (a -> b) -> [a] -> [b] |
|||
const map = (f, xs) => xs.map(f); |
|||
// quot :: Int -> Int -> Int |
|||
const quot = (n, m) => Math.floor(n / m); |
|||
// take :: Int -> [a] -> [a] |
|||
// take :: Int -> String -> String |
|||
const take = (n, xs) => |
|||
'GeneratorFunction' !== xs.constructor.constructor.name ? ( |
|||
xs.slice(0, n) |
|||
) : [].concat.apply([], Array.from({ |
|||
length: n |
|||
}, () => { |
|||
const x = xs.next(); |
|||
return x.done ? [] : [x.value]; |
|||
})); |
|||
// unlines :: [String] -> String |
|||
const unlines = xs => xs.join('\n'); |
|||
// MAIN --- |
|||
return main(); |
|||
})();</lang> |
|||
{{Out}} |
|||
<pre> |
|||
123 -> 123 |
|||
12345 -> 234 |
|||
1234567 -> 345 |
|||
987654321 -> 654 |
|||
10001 -> 000 |
|||
-10001 -> 000 |
|||
-123 -> 123 |
|||
-100 -> 100 |
|||
100 -> 100 |
|||
-12345 -> 234 |
|||
1 -> (Less than 3 digits) |
|||
2 -> (Less than 3 digits) |
|||
-1 -> (Less than 3 digits) |
|||
-10 -> (Less than 3 digits) |
|||
2002 -> (Even digit count) |
|||
-2002 -> (Even digit count) |
|||
0 -> (Less than 3 digits)</pre> |
|||
=={{header|jq}}== |
=={{header|jq}}== |