Reputation:
I need to write a code, that will translate from any base to any( for 1 base it's Turing machine). I should realize 3 functions using only base library: 1)toDecimal base snumber - convert string number to string decimal number 2)fromDecimal toBase snumber - convert from string decimal to string 1-61 base number 3)convertFromTo fromBase toBase snumber snumber I made something, but i don't know how can i work with strings (that's my first question, sorry if i made something wrong) That's the code i made
fromDecimal :: Int ->Int-> String
fromDecimal _ 0 = ""
fromDecimal toBase snumber = fromDecimal toBase (snumber `div` toBase) ++ ["0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" !! k]
where k = snumber `mod` toBase
toDecimal :: Int -> String -> Int
toDecimal base [] = 0
toDecimal base _| base<0 = error "Use positeve base"
toDecimal base snumber = letters (last snumber) + base * toDecimal base (init snumber)
where letters :: Char -> Int
letters ch
| ch == '0' = 0
| ch == '1' = 1
| ch == '2' = 2
| ch == '3' = 3
| ch == '4' = 4
| ch == '5' = 5
| ch == '6' = 6
| ch == '7' = 7
| ch == '8' = 8
| ch == '9' = 9
| ch == 'a' = 10
| ch == 'b' = 11
| ch == 'c' = 12
| ch == 'd' = 13
| ch == 'e' = 14
| ch == 'f' = 15
| ch == 'g' = 16
| ch == 'h' = 17
| ch == 'i' = 18
| ch == 'j' = 19
| ch == 'k' = 20
| ch == 'l' = 21
| ch == 'm' = 22
| ch == 'n' = 23
| ch == 'o' = 24
| ch == 'p' = 25
| ch == 'q' = 26
| ch == 'r' = 27
| ch == 's' = 28
| ch == 't' = 29
| ch == 'u' = 30
| ch == 'v' = 31
| ch == 'w' = 32
| ch == 'x' = 33
| ch == 'y' = 34
| ch == 'z' = 35
| ch == 'A' = 36
| ch == 'B' = 37
| ch == 'C' = 38
| ch == 'D' = 39
| ch == 'E' = 40
| ch == 'F' = 41
| ch == 'G' = 42
| ch == 'H' = 43
| ch == 'I' = 44
| ch == 'J' = 45
| ch == 'K' = 46
| ch == 'L' = 47
| ch == 'M' = 48
| ch == 'N' = 49
| ch == 'O' = 50
| ch == 'P' = 51
| ch == 'Q' = 52
| ch == 'R' = 53
| ch == 'S' = 54
| ch == 'T' = 55
| ch == 'U' = 56
| ch == 'V' = 57
| ch == 'W' = 58
| ch == 'X' = 59
| ch == 'Y' = 60
| ch == 'Z' = 61
| otherwise = error "Wrong number"
Upvotes: 0
Views: 378
Reputation: 476493
A String
is a list of Char
s. You use some functions like (++)
and last
which are not very efficient when working with lists: (++)
works in linear time with the size of the first list, and last
will take linear time in the length of the list.
Often when processing lists, the base case is the empty list []
, and a pattern (x:xs)
with x
the head of the list and xs
the tail of th elist matches with non-empty lists.
We can define a helper function go
that will enumerate over the list, and use a parameter (often named an accumulator) that will keep track of the thus far constructed number.
For each element in the list, we first multiply the accumulator with the base
and then we add the value for the given character. We keep doing that until we reach the end of the list, in which case we return the accumulator:
toInt :: Int -> String -> Int
toInt base
| base <= 0 = error "Invalid base"
| otherwise = go 0
where go n [] = n
go n (x:xs) = go (n * base + letter x) xs
letter :: Char -> Int
letter c
| '0' <= c && c <= '9' = ord c - ord '0'
| 'A' <= c && c <= 'Z' = ord c - ord 'A' + 10
| 'a' <= c && c <= 'z' = ord c - ord 'a' + 36
| otherwise = error "Invalid character"
For the fromDecimal
(perhaps rename it to fromInt
) you can work with an accumulator as well: in that case you use a list that you each time prepend with a character, and when you reach 0
for the value, you can return that accumulator. I leave that as an exercise.
Upvotes: 0