Un'altra idea sarebbe quella di dire: l'ultima cifra conta per 1, il penultimo numero per 10, la cifra prima per 100, eccetera. Quindi per convertire un elenco di cifre in un numero, è necessario invertirlo (per iniziare sul retro), moltiplicare le cifre insieme ai corrispondenti poteri di dieci e aggiungere il risultato insieme.
Per invertire un elenco, utilizzare reverse
, per ottenere le potenze di dieci è possibile utilizzare iterate (*10) 1
(provarlo in GHCi o Abbracci!), Per moltiplicare le cifre corrispondenti di due liste utilizzare zipWith (*)
e aggiungere tutto insieme, utilizzare sum
- aiuta davvero a conoscere alcune funzioni della libreria! Mettendo insieme i pezzi, si ottiene
fromDigits xs = sum (zipWith (*) (reverse xs) (iterate (*10) 1))
Esempio di valutazione:
fromDigits [1,2,3,4]
==> sum (zipWith (*) (reverse [1,2,3,4]) [1,10,100,1000, ....]
==> sum (zipWith (*) [4,3,2,1] [1,10,100,1000, ....])
==> sum [4 * 1, 3 * 10, 2 * 100, 1 * 1000]
==> 4 + 30 + 200 + 1000
==> 1234
Tuttavia, questa soluzione è più lento di quelli con foldl
, a causa della chiamata al reverse
e dal momento che si sta costruendo quei poteri di dieci solo per usarli di nuovo direttamente. Tra l'altro, questo modo di costruire numeri è più vicino al modo in cui la gente di solito pensa (almeno io!), Mentre le -solutions in sostanza usano Horner's rule.
Or way cooler point free - fromDigits = foldl ((+). (* 10)) 0 :) –
Fantastico! Funziona perfettamente. Questo era quello che pensavo di dover fare ma l'hai fatto molto più bello di quanto avrei potuto grazie! – Paul
Quindi funziona, ma non sono esattamente sicuro di come funzioni la parte addDigit. So che foldl prende una funzione e una lista lo fa su tutti gli elementi della lista .. ma addDigit sembra moltiplicare 0 (num) per 10 e quindi aggiungere l'elemento .. che aggiungerebbe solo l'elemento .. quindi cosa sono Mi manca? – Paul