Struggling to extract a section of a list in Haskell - list

I am trying to implement a basic function but I'm out of practice with Haskell and struggling so would really appreciate some help. My question is specifically how to select a section of a list by index. I know how to in other languages but have been struggling
[ x | x <- graph, x!! > 5 && x!! <10 ]
I have been fiddling around with basic list comprehension similar to what is above, and while I know that isn't right I was hoping a similarly simple solution would be available.
If anyone wants more information or felt like helping on the further question I have included more information below, thanks!
type Node = Int
type Branch = [Node]
type Graph= [Node]
next :: Branch -> Graph -> [Branch]
This is the individual question for the "next" function
This is the general set up information but most importantly that the graph is represented as a flattened adjacency matric
Apologies for the two pictures but it seemed the best way to convey the information.

As pointed out in the comments !! does not give you the index of a value in the way it seems you expect. It is just an infix for getting an element of a list.
There is no way to get the index of x like this in Haskell since the x object doesn't keep track of where it is.
To fix this we can make a list of objects that do keep track of where they were. This can be achieved with zip.
zip [0..] graph
This creates a list of tuples each containing their index and the value in graph.
So you can write your list comprehensions as
[ x | (index, x) <- zip [0..] graph, index > 5, index < 10 ]
Now this is not going to be terribly fast since it still needs to go through every element of the list despite the fact that we know no element after the 11th will be used. For speed we would want to use a combination of take and drop.
drop 5 (take 10 graph)
However if we wanted to do some other selections (e.g. all even indexes), we can still go back to the list comprehension.

In this case, you could drop 5 <&> take 4. As in drop 5 x & take 4. Drop skips the first few elements and take leaves out all but the first few left after the drop.

Related

Elixir: Find middle item in list

I'm trying to learn Elixir. In most other languages i've battled with, this would be an easy task.
However, i can't seem to figure out how to access a list item by index in Elixir, which i need for finding the median item in my list. Any clarification would be greatly appreciated!
You will want to look into Enum.at/3.
a = [1,2,3,4,5]
middle_index = a |> length() |> div(2)
Enum.at(a, middle_index)
Note: This is expensive as it needs to traverse the entire list to find the length of the list, and then traverse halfway through the list to find what the actual element is. Generally speaking, if you need random access to an item in a list, you should be looking for a different data structure.
This is how I would do it:
Enum.at(x, div(length(x), 2))
Enum.at/3 retrieves the value at a particular index of an enumerable. div/2 is the equivalent of the Python 2.x / integer division.

Creating a list of players

I want to create a list of "players".
The user of the program can say how many players he wants.
Amount = io:get_line("how many players? \n"),
Int = string:to_integer(Amount),
List = Lists:seq(1,Int).
But now I want to create a list of players in the form [Player1, Player2...PlayerN].
Can someone tell me how to do so?
Remember that string:to_int/1 will return a tuple, not a single value. Also keep in mind that users do some pretty wild stuff in input, so you'll want to check that. (That said... when you're just trying to get a program written for yourself to test an idea, meh, whatever.)
{PlayerCount, _} = string:to_integer(io:get_line("How many players? ")),
Pretty simple. Mess around with this a bit. Input is its own world, and its good to think through this stuff a few times in toy programs (and give yourself insane input to see how the program reacts).
From here you can do a few things. If you just want a list of tuples that indicate you have a player whose serial number is a number, that's easy with a list comprehension:
Players = [{player, Number} || Number <- lists:seq(1, PlayerCount)],
You can write that as a map as well:
Players = lists:map(fun(N) -> {player, N} end, lists:seq(1, PlayerCount)),
I find the list comprehension more readable, though. Another alternative is to write your own custom recursive function. You almost never need to do this, but if you're new to programming it is good practice, and early on its way more readable because you see exactly what is happening each iteration:
player_list(Count) -> player_list(1, Count, []).
player_list(Max, Max, Players) ->
lists:reverse(Players);
player_list(Current, Max, Players) ->
player_list(Current + 1, Max, [make_new_player(Current) | Players]).
Note that the above is equivalent to, but more naturally stated than:
player_list(Current, Max, Players) ->
Next = Current + 1,
case Next == Max of
true -> lists:reverse(Players);
false -> player_list(Next, Max, [make_new_player(Current) | Players])
end.
Matching in function heads is much more clear and readable over the course of a program than a bunch of case and if statements. Over time, though, as I mentioned above, you will eventually stop writing recursive functions yourself (for the most part) and find yourself using a lot of list operations (map, fold, filter, list comprehensions, etc.) as you gain experience.
The details of make_new_player/0,1 are entirely up to you, of course -- you didn't indicate what sort of structure you wanted for their data, but you can do whatever you want there. Here are some other ways that might play out:
[make_new_player(Z) || Z <- lists:seq(1, PlayerCount)]
or
[#player{serial = Z} || Z <- lists:seq(1, PlayerCount)]

Returning a first element from an improper list in Erlang

So I've been trying to implement this function in my module and so far I got this:
EXAMPLE 1.
[2,[3,[4,[5,[6,[7,[8,[]]]]]]]]
I am trying to figure out how I can make it look like a proper list, ie:
EXAMPLE 2.
[2,3,4,5,6,7,8].
I know I have to play with Heads and Tails but I am miserably failing at understanding it.
Any help would be appreciated.
Thanks!
Actually in the example 1 you show proper list. List that just consists of 2 elements - number and another list.
Improper list is different thing - for instance [1|2].
You can turn example 1 into example 2 by lists:flatten.
1> M = [2,[3,[4,[5,[6,[7,[8,[]]]]]]]].
[2,[3,[4,[5,[6,[7,[8,[]]]]]]]]
2> lists:flatten(M).
[2,3,4,5,6,7,8]
The root of the problem is how you have built your list. What you have here:
[2,[3,[4,[5,[6,[7,[8,[]]]]]]]]
is not one list but nested lists each of two elements. When you do [Element,List] this does NOT prepend Element to List but builds a new list with Element as the first element and List as the second element. Note that each list is a proper list but you have not built one list but nested lists.
To prepend Element to List you use the syntax [Element | List]. So:
[2|[3|[4|[5|[6|[7|[8|[]]]]]]]]
which builds the list [1,2,3,4,5,6,7,8].
So [Element | List] and [Element,List] are two very different things, the first prepends an element to the beginning of a list while the second builds a new list of two elements. There is no direct way of appending an element to a list without rebuilding the list.
Not as obvious as it looks at first, but this is a manual way of doing what lists:flatten/1 does (in this particular case, its more interesting otherwise):
proper(L) -> proper([], L).
proper(A, [H|[T]]) -> proper([H|A], T);
proper(A, []) -> lists:reverse(A).

Haskell List Monad State Dependance

I have to write a program in Haskell that will solve some nondeterministic problem.
I think i understand List Monad in 75% so it is oblivious choice but...
(My problem is filling n x m board with ships and water i am given sums of rows and colums every part of ship has its value etd its not important right now).
I want to guard as early as possible to make algoritm effective the problem is that possibility of insertion of ship is dependant from what i am given / what i have inserted in previus moves lets call it board state and i have no idea how to pass it cuz i can't generate a new state from board alone)
My Algoritm is:
1. Initialize First Board
2. Generate First Row trying applying every possible insertion (i can insert sheep verticaly so i need to remember to insert other parts of sheep in lower rows)
3. Solve the problem for smaller board (ofc after generating each 2 rows i check is everything ok)
But i have no idea how can I pass new states cuz as far as i have read about State Monad it generates new state from old state alone and this is impossible for me to do i would want to generate new state while doing operations on value).
I am sorry for my hatred towards Haskell but after few years of programing in imperative languages being forced to fight with those Monads to do things which in other languages i could write almost instantly makes me mad. (well other things in Haskell are fine for me and some of them are actually quite nice).
Combine StateT with the list monad to get your desired behavior.
Here's a simple example of using the non-determinism of the list monad while still keeping a history of previous choices made:
import Control.Monad
import Control.Monad.Trans.Class
import Control.Monad.Trans.State
fill :: StateT [Int] [] [Int]
fill = do
history <- get
if (length history == 3)
then return history
else do
choice <- lift [0, 1, 2]
guard (choice `notElem` history)
put (choice:history)
fill
fill maintains a separate history for each path that it tries out. If it fills up the board it returns successfully, but if the current choice overlaps with a previous choice it abandons that solution and tries a different path.
You run it using evalStateT, supplying an initial empty history:
>>> evalStateT fill []
[[2,1,0],[1,2,0],[2,0,1],[0,2,1],[1,0,2],[0,1,2]]
It returns a list of all possible solutions. In this case, that just happens to be the list of all permutations in which we could have filled up the board.

How to add item to list in prolog

I have a list in prolog that contains several items. I need to 'normalized' the content of this list and write the result to a new list. But I still have problem in doing it.
The following code shows how I did it:
normalizeLists(SourceList, DestList) :-
% get all the member of the source list, one by one
member(Item, SourceList),
% normalize the item
normalizeItem(Item, NormItem),
% add the normalize Item to the Destination List (it was set [] at beginning)
append(NormItem, DestList, DestList).
The problem is in the append predicate. I guess it is because in prolog, I cannot do something like in imperative programming, such as:
DestList = DestList + NormItem,
But how can I do something like that in Prolog? Or if my approach is incorrect, how can I write prolog code to solve this kind of problem.
Any help is really appreciated.
Cheers
Variables in Prolog cannot be modified, once bound by unification. That is a variable is either free or has a definite value (a term, could be another variable). Then append(NormItem, DestList, DestList) will fail for any NormItem that it's not an empty list.
Another problem it's that NormItem it's not a list at all. You can try
normalizeLists([], []).
normalizeLists([Item|Rest], [NormItem|NormRest]) :-
% normalize the item
normalizeItem(Item, NormItem),
normalizeLists(Rest, NormRest).
or (if your Prolog support it) skip altogether such definition, and use an higher order predicate, like maplist
...
maplist(normalizeItem, Items, Normalized),
...