Update 'x'th element of list - Haskell [duplicate] - list

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Replace individual list elements in Haskell?
I have managed to make some progress in this part of my assignment but have attached part of the code below that I have made:
module Grid where
data State = On | Off deriving (Eq, Show)
next :: State -> State
next On = Off
next Off = On
type Row = [State]
updateRow :: Row -> Int -> Row
updateRow (r:rs) x
| x == 0 = next r:rs
-- | otherwise = ........????
As shown in the last line just above, I have managed to get updateRow to work for when x = 0, as shown below (with the 0th element inverted).
*Grid> updateRow [Off,Off,Off,Off] 0
[On,Off,Off,Off]
*Grid>
It all comes unstuck however when I try inverting other elements of this list. I can't seem to 'genralise' a formula in this function.
I also MUST follow THIS type convention:
updateRow :: Row -> Int -> Row
Thanks in advance.

Something like that:
module Grid where
data State = On | Off deriving (Eq, Show)
next :: State -> State
next On = Off
next Off = On
type Row = [State]
updateRow :: Row -> Int -> Row
updateRow (r:rs) x
| x == 0 = next r:rs
| otherwise = r : (updateRow rs (x-1))
updateRow [] x = []

Use the function provided for you in the previous question you asked. It works for lists of any type and I think it does what you want to do here.

How about a general update function?
update i a as = map repl $ zip as [0..] where
repl (a',i') | i == i' = a
| otherwise = a'
I guess there are more performant versions, but this one is easy to understand and good enough for short lists. It replaces the ith element (if there is any) in as with a.

Actually the idea for the otherwise part of your updateRow function is similar to the what you have in the replace of your other question.
The idea is: if x is not zero, then you want to skip the element r (which is at position zero) and call updateRow on rs at a position that is x - something (where something takes into account the one position that you just skipped).
I hope this helps

Related

How to check for non empty list in Ocaml? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 months ago.
Improve this question
I'm trying to learn functional programming with Ocaml and I want to implement a function, which returns the sum of the elements in a list. I want to do it using a while loop, but I can't think of a way to write the check.
I imagined something like this
let sum_it (xs: int list) =
let j = ref 1 in
let add x y = x+y in
while xs <> [] do
j := add !j hd ;
xs = tl done ;
!j ;;
but now it fails with the j := add !j hd ;
Error: This expression has type 'a list -> 'a
but an expression was expected of type int
The OCaml way to analyze the shape of a value is to use pattern matching:
match list with
| [] -> ... (* 1 *)
| a :: q -> ... (* 2 *)
Compared to a language with only conditionals (like C), the advantage of pattern matching is that it directly associate a check to see if a value has a certain shape with the action to run for values of that shape. Combined with the possibility to check if a pattern matching covers all case, this decrease considerably the room for mistakes.
For instance, with
| [] -> ... (* 1 *)
the action 1 on the right hand side of -> is only run if the matched list list is empty whereas the second action
| a :: q -> ... (* 2 *)
is only run if the list has the shape a :: q for some a and q. Moreover, this second action can use the value a of the head of the list and the value q of the tail of the list directly in its body. For instance
| a :: q -> a + List.length q
sums the first element of the list list with the length of its tail.
P.S: The use of while loop for simple recursive function is not optimal. The idiomatic OCaml way is to define a recursive function. Indeed, a while loop may have a very complex flow of data. Contrarily, a pure recursive function will have much more explicit and often simpler flow of data.

ML a real list return a real number

I am currently working on a ML small project and learning how to work with it, but here are some problems that I'm facing but cannot find any source online.
I want to have a function to return the last number of the list, which is a real number list. I wrote a code to return a single element real list, but i will it to be a real number but not a list. here is my code:
fun last [] = nil
| last(head::nil) = [head]
| last(head::list) = last(list)
I thought
last(head::nil)=head
would help get the real number but it just give me an error that:
operator domain: 'Z list list
operand: real list
Thank you!
As melpomene says, nil isn't a value of type real, so it can't be the return type for the empty list. In fact, no value can be returned, because the list is empty! This makes the function last partial. You want to avoid partial functions, because they may crash at runtime. You can define an alternative function, lastOpt:
fun lastOpt [] = NONE
| lastOpt [x] = SOME x
| lastOpt (_::xs) = lastOpt xs
For example,
- lastOpt [1,2,3];
> val it = SOME 3 : int option
- lastOpt [];
> val it = NONE : 'a option
This passes responsibility for handling empty lists explicitly to the caller of lastOpt.
The built-in function List.last was made unsafely with exceptions:
fun last [] = raise Empty
| last [x] = x
| last (_::xs) = last xs
I wouldn't recommend using this.

2d matrix sml inserting to list - simple code

I have an sml-nj project in which I want to work with a 'list of lists' structure, which has "Squares". I'm trying to insert values to the list of lists recursively, but I still haven't understood how to insert elements to a 2d list.
Note - I CAN'T USE 'REF', ONLY http://smlfamily.org/Basis/list.html#SIG:LIST.app:VAL these functions.
datatype SquareContent = Mine | Digit of int | Blank;
datatype Square = Revealed of SquareContent | Concealed of SquareContent;
fun createMineSweeperGrid (n:int)
:(Square list list)=
let
fun createMines (rowCounter:int, colCounter:int
, retGame:Square list list):(Square list list) =
if rowCounter=n then
retGame (* finished all rows, should be n lists of size n*)
else
if colCounter=n then (*finished current row, move on*)
createMines (rowCounter+1, 0, mines,retGame)
else
let
val squareToInsert = Concealed(Mine) (* I wish to insert 'squareToInsert'
to retGame[rowCounter][colCounter], it's done dynamically, but I don't know
how to do that *)
in
createMines (rowCounter, colCounter+1, retGame)
end
in
createMines (0,0,[])
end
I could insert any kind of Square, it's decided dynamically and here I gave example only of concealed Mine so you can help me.. HELP..?
The essential thing to recognize is that in Standard ML, you don't mutate existing structures; rather, you create new ones. (Standard ML does support mutable structures, via ref and its friends, but it's not something to do lightly, and I see that you've already — rightly — ruled it out.)
In general, therefore, inserting something into the middle of a linked list is pretty expensive: it requires "unwinding" the list to the point where you want to insert, then inserting the value, and lastly building a copy of everything you'd unwound. For example, here's a function that would insert a value x at index i of a list:
fun insert (x, 0, L) = x :: L
| insert (x, i, h :: t) = h :: insert (x, i - 1, t)
| insert (_, _, nil) = raise Subscript
Fortunately, your function is written so as to not have to insert anything into the middle of an already-built linked list; rather, if I understand correctly what it's trying to do, it always puts the new square at the beginning of the first list. So:
let
val squareToInsert = Concealed(Mine)
val topRow :: rest = retGame
in
createMines (rowCounter, colCounter+1, (squareToInsert::topRow)::rest)
end
Note that you'll also need to fix another bug, which is that you never actually create new rows: you have a comment about "finished current row, move on", but then it just proceeds exactly the same as if it were still in the same row (just resetting the numbers as if it had moved to a new row). To fix this, use [] :: retGame when you want to add a new row at the top, and use [[]] instead of [] for the initial board (so that it starts out with an empty row).

Change a variable in standard ml list

I wonder when working with list in ml, how to change a variable with specific location of the list. For instance, when I have a list [1,2,3,4], I want to change the list to [1,2,5,4] with the 5 subtitle for the 3. What i'm thinking is to write a function that take a location, the variable and the list, return the new list with the update variable. For example,
change(i, var, list) = let val valup = var in (list # [i]) end
So with this code, if my input is change(2, 5, [1,2,3,4]), my out put will be [1,2,3,4,2] which incorrect compare to [1,2,5,4]. I'm new with ml and not good with the list setup in the language so any help would be really appreciate.
You have to realise that values are not mutable in ML. This means that once you create a value, you can't change it!
So if we have these two statements
x = [2,3,4]
y = 1::x
then y and x live in seperate memory locations on the computer.
What you can do is the following:
fun swapFirst [] y = raise Empty
| swapFirst (x::xs) y = y::xs
val test_swapFirst_00 = [1,2,3,4] = swapFirst [2,2,3,4] 1
which will swap the first element of a list out with something else.
Now I have a feeling that this could be for an answer for some course work, so I'm not going to give a complete code that solves your problem, but this information should at least clear some things up, and make it easier for you to solve the problem!
I come up with the solution for the problem.
fun change(i,v,[]) = raise Error
| change(0, v, x::xs) = v :: xs
| change(i, v, x::xs) = if i < 0 then raise Error
else x :: change((i-1), v, xs)

List Grid Elements

I have managed to make some progress in this part of my assignment but have attached part of the code below that I have made:
module Grid where
data State = On | Off deriving (Eq, Show)
next :: State -> State
next On = Off
next Off = On
type Row = [State]
type Grid = [[State]]
type Point = (Int,Int)
initialRow :: Int -> Row
initialRow w = replicate w Off
updateRow :: Row -> Int -> Row
updateRow (r:rs) x
| x==0 = next r:rs
| otherwise = r : (updateRow rs (x-1))
update :: Grid -> Point -> Grid
update [[]] (x,y) = [[]]
update [(g:gs)] (x,y) = [(updateRow (g:gs) x)]
As shown in the last line just above, I have managed to get update to work for when x = any Int as shown below (with the xth element inverted) - ghci.
*Grid> update [[Off,Off,Off,Off]] (2,0)
[[Off,Off,On,Off]]
*Grid>
It all comes unstuck however when I try working with multiple lists such as this, or select a certain list within the list to update the xth element:
*Grid> update [[Off,Off,Off,Off],[Off,Off,Off,Off]] (2,0)
*** Exception: Grid.hs:(24,0)-(25,47): Non-exhaustive patterns in function update
I can't seem to 'genralise' a formula in this function.
I also MUST follow THIS type convention:
updateRow :: Grid -> Point -> Grid
Basically, what I would like to do is update from something like this...
[[Off,Off,Off,Off],
[Off,Off,Off,Off],
[Off,Off,Off,Off],
[Off,Off Off,Off]]
to this:
[[Off,Off,Off,Off],
[Off,Off,**On**,Off],
[Off,Off,Off,Off],
[Off,Off Off,Off]]
where 'x' is the value of the element and 'y' is the value of the list within the list IYGWIM.
Thanks in advance.
update :: Grid -> Point -> Grid
update [[]] (x,y) = [[]]
This checks for a list that contains the empty list.
update [(g:gs)] (x,y) = [(updateRow (g:gs) x)]
This checks for a list that contains one list, the latter containing at least one element (bound to the variable g).
You want to check for a list that contains multiple lists.
The pattern should look like:
update :: Grid -> Point -> Grid
update [[]] (x, y) = [[]]
update (row:rows) (x, 0) = updateRow row x : rows
update (row:rows) (x,y) = -- I'll let you fill this, notice the 0 on the previous line
Remember a Grid is just a list of Rows.
The second line now means "if you want to update the 0th line of this grid, then update the first row", the last line should mean "if you want to update the yth line of this grid, then leave the first one as is, and recursively update the rest of the rows" (of course, y must be changed accordingly in the recursive call).
Here is the solution. After some thought, I came out with the following and filled the final line of the above 'pattern':
...
update (g:gs) (x,y) = g : update gs (x,(y-1))