tags:

views:

121

answers:

1

I'm having a bit difficulty figuring out, how to get each of the processed chars back to an int value.

The function should work like: val caesar = fn : int * int -> int

So if k = 2466 and n = 2, then the output should be 4688

Hope the code isn't too weird (I'm a SML newbie).

 (* Load Libs *)
    load "Int";
    load "Real";
    load "String";
    load "Char";
    load "List";


    fun caesar (k, n) =
      let
        fun k_string (i) = Int.toString(i)
        fun item_k_char (x, y) = Char.ord (List.nth (x, y))

        val val_k_string = k_string(k)
        val k_explode = String.explode(val_k_string)
        val counter = ref 0
        val counter_end = (String.size(val_k_string) - 1)

      in 
        while (!counter >= counter_end) do (
          item_k_char(k_explode, !counter) + n;
          counter := !counter + 1
        )
      end;
+1  A: 

A while loop isn't the best tool here. Instead you can use map which executes a given function for each item in a given list and returns a new list containing the result of each call to the function.

In other words: map (fn c => (Char.ord c) + 2) [#"2", #"4", #"6", #"6"] will return [52,54,56,56]. You can the convert this back to char and use String.implode to get the string "4688".

You probably also want to add some logic so that the numbers "wrap around", i.e. caesar (7,7) becomes 4.

So all in all your code becomes:

fun caesar (k, n) =
  let
    val val_k_string = Int.toString k
    val k_explode = String.explode val_k_string
    val ints = map (fn c => (Char.ord c) + n) k_explode
    val wrappedAroundInts = map (fn i => (i - 48) mod 10 + 48) ints
    val chars = map Char.chr wrappedAroundInts
    val string = String.implode chars
  in
    Option.valOf (Int.fromString string)
  end
sepp2k
Wooh thx :) Could you explain the wrappedAroundInts value function, I'm not 100% sure I understand it. Another thing, I need to add an exception for a variant of fun caesar, where I check if k is = 8. Can it be done like this? caesar2(k, n : int) = if Option.valOf (Int.fromString (String.size (Int.toString (k)))) != 8 then raise Fail "k must be 8 characters long"
TBK
@TBK: The wrapping works like this: `Char.ord` returns an int between 48 (ASCII value of `#"0"`) and 57 (ASCII value of `#"9"`). After adding `n` the value may be larger than 57 (and thus no longer represent a digit). To get around that, we subtract 48 and take the result modulo 10. Now we have a number between 0 and 9. By adding 48 again we get a number between 48 and 57 again and thus a valid digit.
sepp2k
@TBK: If you want to check whether `k` is 8, you can just do `if k = 8 then`. If you want to check whether `k` has 8 digits, you can do `if String.size (Int.toString k) = 8`. If you want to check whether `k` does not have 8 digits, you can use `if String.size (Int.toString k) = 8`. There is no need to use `fromString` as `size` returns an integer.
sepp2k
Super, I really appreciate it :D
TBK
@TBK: Ehrm, in my last comment I meant to say "If you want to check whether k does not have 8 digits, you can use `if String.size (Int.toString k) <> 8`" (`<>` instead of `=`). And you're welcome.
sepp2k
Yup, saw that and looked up the Int lib where I also figured out it must be <>. Thanks again :)
TBK