Niels A
Niels A

Reputation: 11

How to update a value with the result from a function

let rec insert v i l =
    match i, l with
    | 0, xs -> v::xs
    | i, x::xs -> x::insert v (i - 1) xs
    | i, [] -> failwith "index out of range"

let rec remove i l =
   match i, l with
   | 0, x::xs -> xs
   | i, x::xs -> x::remove (i - 1) xs
   | i, [] -> failwith "index out of range"    

The su value looks as follows:

[['5'; '3'; '*'; '*'; '7'; '*'; '*'; '*'; '*'];
['6'; '*'; '*'; '1'; '9'; '5'; '*'; '*'; '*'];
['*'; '9'; '8'; '*'; '*'; '*'; '*'; '6'; '*'];
['8'; '*'; '*'; '*'; '6'; '*'; '*'; '*'; '3'];
['4'; '*'; '*'; '8'; '*'; '3'; '*'; '*'; '1'];
['7'; '*'; '*'; '*'; '2'; '*'; '*'; '*'; '6'];
['*'; '6'; '*'; '*'; '*'; '*'; '2'; '8'; '*'];
['*'; '*'; '*'; '4'; '1'; '9'; '*'; '*'; '5'];
['*'; '*'; '*'; '*'; '8'; '*'; '*'; '7'; '9']]

The goal is to replace one of the lists in su, with the new list generated from the replace function, and then make that result saved as the new su. This is what i have made so far.

let replace (r,s,v : int) =
   remove (s-1) su.[r-1] 
   insert (char(string(v))) (s-1) su.[r-1]

with the call replace (2,2,4), su should end up as follows:

[['5'; '3'; '*'; '*'; '7'; '*'; '*'; '*'; '*'];
['6'; '4'; '*'; '1'; '9'; '5'; '*'; '*'; '*'];
['*'; '9'; '8'; '*'; '*'; '*'; '*'; '6'; '*'];
['8'; '*'; '*'; '*'; '6'; '*'; '*'; '*'; '3'];
['4'; '*'; '*'; '8'; '*'; '3'; '*'; '*'; '1'];
['7'; '*'; '*'; '*'; '2'; '*'; '*'; '*'; '6'];
['*'; '6'; '*'; '*'; '*'; '*'; '2'; '8'; '*'];
['*'; '*'; '*'; '4'; '1'; '9'; '*'; '*'; '5'];
['*'; '*'; '*'; '*'; '8'; '*'; '*'; '7'; '9']]

Upvotes: 1

Views: 94

Answers (3)

Olaf
Olaf

Reputation: 3986

I have a solution for your problem. It consists of two functions. The first replaces a value v in a list at positions i. The second function calls the first one and replaces the list with the number i.

let rec replaceInList v i lst =
    match i, lst with
    | _, []    -> []
    | 1, x::xs -> v::xs
    | i, x::xs -> x::replaceInList v (i-1) xs

let rec replaceInMatrix v i j matrix =
    match i, matrix with
    | _, []    -> []
    | 1, x::xs -> (replaceInList v j x)::xs
    | i, x::xs -> x::replaceInMatrix v (i-1) j xs

You can test both in the F# REPL:

> replace 9 2 [1;2;3];;  

val it : int list = [1; 9; 3]    


> replaceInMatrix 99 2 2 [[1;2;3];[4;5;6];[7;8;9]];;

val it : int list list = [[1; 2; 3]; [4; 99; 6]; [7; 8; 9]]

The second function is basically a repetition of the first one. Maybe there is a way to create a more general implementation but unfortunately I'm not fluent enough in F# to come up with a better solution. Maybe someone else...

Upvotes: 0

Functional_S
Functional_S

Reputation: 1159

To transform a list of lists, two cascaded List.map are needed. With List.mapi the index of the element is also given. With the column and row index it is easy to do the replacement at the correct position.

let su =
 [['5'; '3'; '*'; '*'; '7'; '*'; '*'; '*'; '*'];
  ['6'; '*'; '*'; '1'; '9'; '5'; '*'; '*'; '*'];
  ['*'; '9'; '8'; '*'; '*'; '*'; '*'; '6'; '*'];
  ['8'; '*'; '*'; '*'; '6'; '*'; '*'; '*'; '3'];
  ['4'; '*'; '*'; '8'; '*'; '3'; '*'; '*'; '1'];
  ['7'; '*'; '*'; '*'; '2'; '*'; '*'; '*'; '6'];
  ['*'; '6'; '*'; '*'; '*'; '*'; '2'; '8'; '*'];
  ['*'; '*'; '*'; '4'; '1'; '9'; '*'; '*'; '5'];
  ['*'; '*'; '*'; '*'; '8'; '*'; '*'; '7'; '9']]

let replace su col row r =
    List.mapi (fun i xs -> 
    List.mapi (fun j x  -> 
               if (i+1)=col && (j+1)=row 
               then r else x) xs) su

replace su 2 2 '4'

Upvotes: 1

Helge Rene Urholm
Helge Rene Urholm

Reputation: 1188

Unless you insists on doing it recursively the following may do the trick:

let su =
 [['5'; '3'; '*'; '*'; '7'; '*'; '*'; '*'; '*'];
  ['6'; '*'; '*'; '1'; '9'; '5'; '*'; '*'; '*'];
  ['*'; '9'; '8'; '*'; '*'; '*'; '*'; '6'; '*'];
  ['8'; '*'; '*'; '*'; '6'; '*'; '*'; '*'; '3'];
  ['4'; '*'; '*'; '8'; '*'; '3'; '*'; '*'; '1'];
  ['7'; '*'; '*'; '*'; '2'; '*'; '*'; '*'; '6'];
  ['*'; '6'; '*'; '*'; '*'; '*'; '2'; '8'; '*'];
  ['*'; '*'; '*'; '4'; '1'; '9'; '*'; '*'; '5'];
  ['*'; '*'; '*'; '*'; '8'; '*'; '*'; '7'; '9']]


let replaceV s v i c = 
  if i + 1 = s then v else c 

let replaceL r s v i l = 
 let replaceV' = replaceV s v
 match i with
 | _ when r = i + 1 ->  l |> List.mapi replaceV'
 | _ ->  l

// x y value
let replace r s v =
 let replace' = replaceL r s v
 su |> List.mapi replace'


replace  2 2 '4'

I'm not to happy with this code myself though...

If you insists on doing it recursively and using your code, you possible see by this example how/what you may do to your own.

Upvotes: 1

Related Questions