I'm trying to display the sorting process of quicksort with Elm
[ 5, 8, 6, 2, 4, 1, 0, 3, 10, 7, 9 ]
[2,4,1,0,3] 5 [8,6,10,7,9]
[1,0] 2 [4,3] [6,7] 8 [10,9]
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
Right now i can get the first 2 lines but I'm unsure how to approach this in a recursive manner.
list_to_html : List (List Int) -> Html msg
list_to_html x =
div [] [ x |> toString |> text ]
quicksort_partition : List Int -> Html msg
quicksort_partition list =
case list of
x :: xs ->
let
lower =
List.filter ((>=) x) xs
higher =
List.filter ((<) x) xs
in
list_to_html [ lower, [ x ], higher ]
[] ->
list_to_html []
This outputs:
[ 5, 8, 6, 2, 4, 1, 0, 3, 10, 7, 9 ]
[2,4,1,0,3] [5] [8,6,10,7,9]
If you are trying to get that kind of output, direct recursion inside the view isn't going to work well. Instead, I would approach it as writing a variation of quicksort which logs the state along the way.
Here is an example of quicksort which also returns a list of logs. The type aliases are included to try and make the function annotation more clear:
type alias Depth =
Int
type alias Log comparable =
( Depth, List comparable, comparable, List comparable )
quicksortLog : Depth -> List comparable -> ( List comparable, List (Log comparable) )
quicksortLog depth list =
case list of
[] ->
( [], [] )
x :: xs ->
let
( lower, lowerLog ) =
quicksortLog (depth + 1) (List.filter ((>=) x) xs)
( higher, higherLog ) =
quicksortLog (depth + 1) (List.filter ((<) x) xs)
log =
( depth, lower, x, higher )
in
( lower ++ [ x ] ++ higher, log :: lowerLog ++ higherLog )
Given that result, you could then write a view which displays the data in the way you see fit.
Related
My current code is below. I think all of the functions, except for the last one are correct. What I'm trying to achieve with changeValueMatrix is to give a matrix, a matrix position and a value and then that value will replace the one that is at the current position. I've managed to reach the position and to change the value but I can only return the row on which I changed it and not the whole matrix. I am a Haskell beginner and I've only learned recursion just now but it would be ideal to use it here if possible.
type Matrix a = [[a]]
type MatrixDimension = (Int,Int)
type MatrixPosition = (Int,Int)
matrixDimension :: Matrix a -> MatrixDimension
matrixDimension m = (length m, length (head m))
returnValueList :: Int -> [a] -> a
returnValueList 0 (x:xs) = x
returnValueList i(x:xs) = returnValue (i-1)(xs)
changeValueList :: Int -> a -> [a] -> [a]
changeValueList 0 value (x:xs) = (value:xs)
changeValueList i value (x:xs) = x:(changeValueList (i-1) (value) (xs))
returnValueMatrix :: MatrixPosition-> Matrix a -> a
returnValueMatrix(m,n) matrix = returnValueList n (returnreturnValueList matrix)
changeValueMatrix :: MatrixPosition -> a -> Matrix a -> Matrix a
changeValueMatrix(0,c) value (x:xs) = a:xs
where a = changeValueList c value x
changeValueMatrix(r,c) valor (x:xs) =
where
row = returnValueList r (x:xs)
b = changeValueList c value row
You can build changeValueMatrix from the functions you’ve already defined:
changeValueMatrix :: MatrixPosition -> a -> Matrix a -> Matrix a
changeValueMatrix (r, c) value matrix
= changeValueList r -- (3)
(changeValueList c value -- (2)
(returnValueList r matrix)) -- (1)
matrix
At (1) you look up the row at index r in matrix, at (2) you replace the element at column c in that row with value, and at (3) you replace the row at index r in matrix with the modified row. For example:
-- Given: mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
changeValueMatrix (1, 1) 0 mat
==
changeValueList 1
(changeValueList 1 0
(returnValueList 1 mat))
mat
==
changeValueList 1
(changeValueList 1 0 [4, 5, 6])
mat
==
changeValueList 1 [4, 0, 6] mat
==
[ [1, 2, 3]
, [4, 0, 6]
, [7, 8, 9]
]
If you want a version of this using explicit recursion, which only traverses the rows once, you can inline the definition of changeValueList into changeValueMatrix:
changeValueMatrix (0, c) value (x : xs)
= changeValueList c value x : xs
changeValueMatrix (r, c) value (x : xs)
= x : changeValueMatrix (r - 1, c) value xs
Be aware that your code has a few failure cases, though:
Negative indices will produce infinite loops because you only test for 0 and recur with i - 1 on any other number
Overly large indices will run into the end of the list and crash because you don’t handle the [] case—the pattern matches are non-exhaustive, which the compiler will point out when enabling all warnings with -Wall
Similarly, matrices of zero width or height are representable, but these functions don’t handle the possibility (e.g. matrixDimension calls head on a possibly-empty list); you can avoid this using Data.List.NonEmpty or Data.Array as your backing type, the latter of which is also more efficient
I am trying to solve the problem on HackerRank https://www.hackerrank.com/challenges/breaking-best-and-worst-records/problem
What the question ask is to display 2 values no of times the record is broken for min score and highest score
I have wrote the algorithm to find it. I am stuck with how to output 2 values.
Following is my solution. Currently it display's the number of highest record broken. I want to show 2 values so that it passes the test in hackerrank.
mxscore::(a,a,a,a) -> a
mxscore (_,a,_,_) = a
mnscore::(a,a,a,a) -> a
mnscore (a,_,_,_) = a
lscore :: (a, a,a,a) -> a
lscore (_,_,a,_) = a
hscore :: (a, a,a,a) -> a
hscore (_,_,_,a) = a
main = interact $ show . hscore .solve . map read . tail . words
solve::[Int] -> (Int, Int, Int, Int)
solve (x:xs) = solve1 x xs
where solve1 d dx = foldl(\acc x -> if x > mxscore acc
then (mnscore acc, x, lscore acc, hscore acc + 1)
else if x < mnscore acc then (x, mxscore acc, lscore acc + 1, hscore acc) else acc ) (d,d,0,0) dx
Current solution works as follows
*Main> solve [10, 5, 20, 20, 4, 5, 2, 25, 1]
(1,25,4,2)
where 4 is number of time lowest record is broken
and 2 is number of time highest record is broken
*Main> solve [3, 4, 21, 36, 10, 28, 35, 5, 24, 42]
(3,42,0,4)
where 0 is number of time lowest record is broken
and 4 is number of times highest record is broken
The first number is no. of scores
The second line is Score
Input:
9
10 5 20 20 4 5 2 25 1
Output :
2 4
Ans. explanation 2 is the number of time the records were broken for highest score
4 is the number of time the records were broken of lowest score
I found the solution to the question. I created 1 more function that would override the show
mxscore::(a,a,a,a) -> a
mxscore (_,a,_,_) = a
mnscore::(a,a,a,a) -> a
mnscore (a,_,_,_) = a
lscore :: (a, a,a,a) -> a
lscore (_,_,a,_) = a
hscore :: (a, a,a,a) -> a
hscore (_,_,_,a) = a
main = interact $ show1 .solve . map read . tail . words
show1::(Int, Int, Int, Int) -> String
show1 (_,_,a,b) = show b ++ " " ++ show a
solve::[Int] -> (Int, Int, Int, Int)
solve (x:xs) = solve1 x xs
where solve1 d dx = foldl(\acc x -> if x > mxscore acc
then (mnscore acc, x, lscore acc, hscore acc + 1)
else if x < mnscore acc then (x, mxscore acc, lscore acc + 1, hscore acc) else acc ) (d,d,0,0) dx
Thanks
I have a simple question about list in haskell. (I am a beginner in haskell)
I would know how can i replace an element in an array but as simple as possible.
[1, 2, 4, 4, 5]
to
[1, 2, 3, 4, 5]
And also how can i happend a number to a list
[1, 2, 3, 4]
to
[1, 2, 3, 4, 5]
I have already read that tutorial : http://learnyouahaskell.com/starting-out
I was thinking about this for the first problem :
array = [1, 2, 4, 4, 5]
array[2] = 2
and that for the second :
array = [1, 2, 3, 4]
array ++ [5]
Ps : the array ++ [5] works with ghci but when i do like that in code :
array = [1, 2, 3, 4]
modifyarray = do
print $ array !! 2
array ++ [5]
print $ array !! 4
that doesn't work ...
EDIT :
module Main where
import Lib
import System.Environment
import System.Exit
redPoint = [3,4,2]
fillArray file x = do
let line = lines file
print $ line
replaceAt x y = map (\(i,v) -> if (i==x) then y else v) . zip [1..]
replaceArray = do
print $ redPoint !! 2
replaceAt 2 9 redPoint
print $ redPoint !! 2
openfile a n path = do
file <- readFile path
fillArray file 0
replaceArray
exit = exitWith ExitSuccess
error_exit = exitWith (ExitFailure 84)
parse [a, n, path] = openfile a n path >> exit
parse [] = error_exit
main = do
getArgs >>= parse
This error :
Couldn't match type ‘[]’ with ‘IO’
Expected type: IO Integer
Actual type: [Integer]
• In a stmt of a 'do' block: replaceAt 2 9 redPoint
In the expression:
do print $ redPoint !! 2
replaceAt 2 9 redPoint
print $ redPoint !! 2
In an equation for ‘replaceArray’:
replaceArray
= do print $ redPoint !! 2
replaceAt 2 9 redPoint
print $ redPoint !! 2
you don't do mutation on the list but create a new list from the given list.
an example, without any error handling...
> replaceAt x y = map (\(i,v) -> if (i==x) then y else v) . zip [1..]
> replaceAt 3 10 [1..5]
[1,2,10,4,5]
create an indexed list by zipping with the counting numbers, write a map function to change the value at the desired index.
Lens! (Maybe it is overhead but anyway)
_drop 0 = id
_drop n = _tail . _drop (n - 1)
And use case
[1..5] & _drop 1 %~ (5:) -- [1,5,2,3,4]
Using lens
> import Control.Lens
Control.Lens> [1..5] & (ix 1) .~ 5
[1,5,3,4,5]
First of all, please ask only one question in a single post.
Here is an implementation which doesn't use Lens and more suitable for a beginner. The replaceAt function error handling needs some brain work. Without error handling it could be fitted in a single line.
These functions work on infinite lists, too. Execution time of replaceAt depends of i. Replacing element in the end of the list is slower than in the beginning because of the recursive nature of Haskell's lists.
module ListOperations where
replaceAt :: Int -> a -> [a] -> [a]
replaceAt i x xs = case (i<0, splitAt i xs) of
(False,(start,(_:end))) -> start ++ (x:end)
_ -> error "Index out of bounds"
append :: a -> [a] -> [a]
append x xs = xs ++ [x]
I'm trying to figure out what \\ means in Haskell?
I've got a program that runs perfectly when compiled, implying that \\ is a built-in function, since it's not defined anywhere in the program. However, in GHCi, if I try to use it in the same manner, I get an error saying it's not in the scope.
Does it mean something special in each context?
Here is my code;
module Main where
import Data.List
numbersA = [1, 105, 103, 7, 4, 102, 3, 101, 107, 8, 9]
numbersB = [6, 9, 7, 8, 1, 5, 3, 2, 4]
type Number = Integer
type Run = [Number]
extractRuns :: [Number] -> [Run]
extractRuns [] = []
extractRuns xs = run : extractRuns xs'
where run = buildRun (head xs) (tail xs)
xs' = xs \\ run
buildRun :: Number -> [Number] -> Run
buildRun seed numbers
| endRun = [seed]
| otherwise = seed : buildRun seed' numbers'
where endRun = successors == []
successors = filter (.#. seed) numbers
numbers' = numbers \\ [seed]
seed' = head successors
(.#.) :: Number -> Number -> Bool
x .#. y = x /= y && abs (x - y) < 10
runs = extractRuns numbersA
main = print runs
\\ is the list difference operator. You can use it in GHCi you just have to import Data.List first.
Prelude> :m Data.List
Prelude Data.List> [1..5]\\[3,4]
[1,2,5]
On a sidenote, this is why I'd suggest avoiding mass imports like import Data.List and to be more specific import Data.List ( (\\) ) so you can be more aware of just what you're importing.
It is the list difference operation. Figuring things like this out is easy if you know to use hoogle.
How can I build an infinite matrix with numbers placed in it diagonally with list comprehension?
[[ 1, 2, 4, 7, 11, ...],
[ 3, 5, 8, 12, 17, ...],
[ 6, 9, 13, 18, 24, ...],
[10, 14, 19, 25, 32, ...],
...]
I've tried to do it like this:
firstColumn = take 6 $ map fst $ iterate (\(a,b) -> (a+b,b+1)) (1,2)
matr :: [[Int]]
matr = [take 6 $ map fst $ iterate (\(x,y) -> (x+y, y+1)) (a, i) | a <- firstColumn, let i = 1]
But how can I pass (i + 1) to next every row (in other words, how do I iterate for additional rows)
By finding a formula for the x and y indices, f.e.:
[[ 1 + (x + y) * (x + y + 1) `div` 2 + y | x <- [0..]] | y <- [0..]]