List in Prolog with elements in round brackets - list

Good Morning
I have list similiar to this: [(1-4), (2-4), (3-4)]. I'd like to write only first/second/third part of round bracket. I wrote a function:
write_list([]).
write_list([Head|Tail]) :-
write(Head), nl,
write_list(Tail).
It only writes whole round bracket:
1-4
2-4
3-4
I'd like my output to be the 1st element of round bracket:
1
2
3
I'll be grateful for any help :D

Here you are:
write_list([]).
write_list([(A-_)|Tail]) :-
writeln(A),
write_list(Tail).
Query:
?- write_list([(1-4),(2-4),(3-4)]).
1
2
3
true
writeln/1 is simply write/1 followed by nl .

You don't really want to write the results but provide them as an argument. Many beginners in Prolog get stuck on this point. Also, it's such a common pattern to apply the same logic to each list element that Prolog has a predicate called maplist for doing the work for you:
first_subterm(A-_, A). % First subterm of `A-_` is `A`
first_subterms(PairList, FirstSubTerms) :-
maplist(first_subterm, PairList, FirstSubTerms).
And you would call it like so:
| ?- first_subterms([(1-4), (2-4), (3-4)], FirstSubTerms).
FirstSubTerms = [1,2,3]
yes
| ?-
The long-hand recursive form would be similar to what was given in the other answer:
first_subterms([], []). % The list of first subterms of [] is []
first_subterms([(A-_)|Pairs], [A|SubTerms]) :-
first_subterms(Pairs, SubTerms).
Note that the "round brackets" are parentheses and, in Prolog, in this context only perform a grouping of the term. It turns out that [(1-4), (2-4), (3-4)] here behaves the same, therefore, as [1-4, 2-4, 3-4] since the , is lower precedence than - in the list notation. So this is also the behavior:
| ?- first_subterms([1-4, 2-4, 3-4], FirstSubTerms).
FirstSubTerms = [1,2,3]
yes
| ?-

Related

Constructing list from user input in Prolog

I recently encounter the following problem in Prolog: Define a predicate avg_num/0 that interactively prompts the user to input a series of numbers (or the word "stop" without quotation marks to end the process). The program outputs the average of these numbers.
In Prolog terminal/interpreter, the program should run like this:
?- avg_sum.
?- Enter a number (or stop to end): 2.
?- Enter a number (or stop to end): |: 3.
?- Enter a number (or stop to end): |: 7.
?- Enter a number (or stop to end): |: stop.
The average is 4.
true.
My idea is to store the value into a list, and then compute the average of numbers of that list using the following code.
% finding the sum of numbers of a list
sumlist([],0).
sumlist([H|T],Sum):- sumlist(T,SumTail), Sum is H + SumTail .
% finding the average of the numbers in a list
average(List,A):- sumlist(List,Sum), length(List,Length), A is Sum / Length .
The problem is then reduced to: how to store the number from user input to a list? Somehow I feel that I need to initialize the empty list at the beginning, but I don't know where to put it. I've tried the following piece of code (this is incomplete though):
avg_sum:- write('Enter a number (or stop to end): '), process(Ans).
process(Ans):- read(Ans),Ans \= "stop", append(X,[Ans],L).
% this part is still incomplete and incorrect.
It seems that I need to initialize the empty list, but I don't know where.
You're almost there. As you said, you need to keep a list of inputs and then do a final computation once the entire list is known. Such a list (or other object keeping intermediate data) is often called an accumulator.
Here is one way of implementing this. It is based on two auxiliary predicates, one for doing the I/O part and one for doing the computation.
We start the computation with an empty list, as you said.
avg_num :-
avg_num([], Average),
write('The average is '), write(Average), writeln('.').
(Recall that in Prolog you can overload predicate names with different arities, i.e., avg_num/0 is a separate predicate from avg_num/2.)
Now avg_num/2 can ask for an input and hand off processing of that input to process/3:
avg_num(Accumulator, Average) :-
write('Enter a number (or stop to end): '),
read(Answer),
process(Answer, Accumulator, Average).
Only in process/3 do we either consume the accumulator by computing its average if stop was input, or (if different from stop) by simply adding the answer to the accumulator and continuing.
process(stop, Accumulator, Average) :-
average(Accumulator, Average).
process(Answer, Accumulator, Average) :-
dif(Answer, stop),
avg_num([Answer | Accumulator], Average).
Note that the order of the numbers in the list does not matter for computing the average, so we can add the input at the front of the list, which is easier than appending at the end.
The mutual recursion between the avg_num/2 and process/3 predicates is not necessarily easy to understand, especially because the names are not very well chosen.
In practice, I would get rid of process/3 by simplifying avg_num/2 like this:
avg_num(Accumulator, Average) :-
write('Enter a number (or stop to end): '),
read(Answer),
( Answer = stop
-> average(Accumulator, Average)
; avg_num([Answer | Accumulator], Average) ).
I would separate out a predicate that reads the list, then handle the list afterwards.
Here's one way to read in the list until an ending term, End:
% read_list_until
%
read_list_until(L, End) :-
( read_element(E, End)
-> L = [E|L1],
read_list_until(L1, End)
; L = []
).
read_element(E, End) :-
read(E),
dif(E, End).
This has the following behavior:
2 ?- read_list_until(L, stop).
|: 1.
|: 2.
|: 3.
|: stop.
L = [1, 2, 3].
3 ?-
Then you can just use standard Prolog predicates to take the average:
avg_list(L, Avg) :-
read_list_until(L, stop),
sum_list(L, Sum),
length(L, Num),
Avg is Sum / Num.

Haskell manipulating elements of a list

So lets say i have a certain string and i want to check the elements of the string, whether they are numbers or characters. Each number has to be replaced with the number 1 and each character with the number 2 and at the end it has to be shown the final result when you sum all numbers.
Example: function "123abc" has to give a result 9
I've already come up with a solution using lists comprehensions and pattern matching, but i need to be able to give a solution without using them, meaning only elem,head,tail,reverse,map,sum etc. All has to be 1 function, now a few combined as one.
You may do as follows;
import Data.Char (isDigit)
import Data.Bool (bool)
getsum :: String -> Int
getsum = sum . map (bool 2 1 . isDigit)
*Main> getsum "1234abc"
10

Match list of incrementing integers using regex

Is it possible to match a list of comma-separated decimal integers, where the integers in the list always increment by one?
These should match:
0,1,2,3
8,9,10,11
1999,2000,2001
99,100,101
These should not match (in their entirety - the last two have matching subsequences):
42
3,2,1
1,2,4
10,11,13
Yes, this is possible when using a regex engine that supports backreferences and conditions.
First, the list of consecutive numbers can be decomposed into a list where each pair of numbers are consecutive:
(?=(?&cons))\d+
(?:,(?=(?&cons))\d+)*
,\d+
Here (?=(?&cons)) is a placeholder for a predicate that ensures that two numbers are consecutive. This predicate might look as follows:
(?<cons>\b(?:
(?<x>\d*)
(?:(?<a0>0)|(?<a1>1)|(?<a2>2)|(?<a3>3)|(?<a4>4)
|(?<a5>5)|(?<a6>6)|(?<a7>7)|(?<a8>8))
(?:9(?= 9*,\g{x}\d (?<y>\g{y}?+ 0)))*
,\g{x}
(?(a0)1)(?(a1)2)(?(a2)3)(?(a3)4)(?(a4)5)
(?(a5)6)(?(a6)7)(?(a7)8)(?(a8)9)
(?(y)\g{y})
# handle the 999 => 1000 case separately
| (?:9(?= 9*,1 (?<z>\g{z}?+ 0)))+
,1\g{z}
)\b)
For a brief explanation, the second case handling 999,1000 type pairs is easier to understand -- there is a very detailed description of how it works in this answer concerned with matching a^n b^n. The connection between the two is that in this case we need to match 9^n ,1 0^n.
The first case is slightly more complicated. The largest part of it handles the simple case of incrementing a decimal digit, which is relatively verbose due to the number of said digits:
(?:(?<a0>0)|(?<a1>1)|(?<a2>2)|(?<a3>3)|(?<a4>4)
|(?<a5>5)|(?<a6>6)|(?<a7>7)|(?<a8>8))
(?(a0)1)(?(a1)2)(?(a2)3)(?(a3)4)(?(a4)5)
(?(a5)6)(?(a6)7)(?(a7)8)(?(a8)9)
The first block will capture whether the digit is N into group aN and the second block will then uses conditionals to check which of these groups was used. If group aN is non-empty, the next digit should be N+1.
The remainder of the first case handles cases like 1999,2000. This again falls into the pattern N 9^n, N+1 0^n, so this is a combination of the method for matching a^n b^n and incrementing a decimal digit. The simple case of 1,2 is handled as the limiting case where n=0.
Complete regex: https://regex101.com/r/zG4zV0/1
Alternatively the (?&cons) predicate can be implemented slightly more directly if recursive subpattern references are supported:
(?<cons>\b(?:
(?<x>\d*)
(?:(?<a0>0)|(?<a1>1)|(?<a2>2)|(?<a3>3)|(?<a4>4)
|(?<a5>5)|(?<a6>6)|(?<a7>7)|(?<a8>8))
(?<y>
,\g{x}
(?(a0)1)(?(a1)2)(?(a2)3)(?(a3)4)(?(a4)5)
(?(a5)6)(?(a6)7)(?(a7)8)(?(a8)9)
| 9 (?&y) 0
)
# handle the 999 => 1000 case separately
| (?<z> 9,10 | 9(?&z)0 )
)\b)
In this case the two grammars 9^n ,1 0^n, n>=1 and prefix N 9^n , prefix N+1 0^n, n>=0 are pretty much just written out explicitly.
Complete alternative regex: https://regex101.com/r/zG4zV0/3

Within my adhoc specific function how do I add commas when printing a list of integers

With input being:
"I am what I
am, and I (765) do not like Spam. Abc2. Abc3."
My code makes an output of:
abc 2
am 1 2
and 2
do 2
i 1 2
like 2
not 2
spam 2
what 1
Where each word is listed along with the line number it appears on.
Question: How do you print the statement below where you get commas between the line numbers like so:
abc 2
am 1,2
and 2
do 2
i 1,2
like 2
not 2
spam 2
what 1
Here is the code I have that takes a list with tuples formatted like this
[([1, 2], "a"), ([1], "b"), ([1], "c"), ([2], "dd")]
and prints it into my current output which I listed above:
combineInts listTuple = map f $ groupBy ((==) `on` fst) $ sortBy (compare `on` fst) $ map swap listTuple
where f xs#(x:_) = (map snd xs, fst x)
printListTuples listTuple = unlines [ ys ++ " " ++ unwords (map show x) | (x, ys) <- listTuple ]
If I can get help figuring out how to get those commas in between the line numbers it would be useful and be much more readable.
There's an easy way, and there's a hard way. The easy way is to use the Show instance for lists and a couple really simple list functions. The other really simple way is to use just one list function. Cn you see how? The harder bit more educational) way is to write it yourself. Can you come up with the base cases and the recursive case?

Finding the max sum of elements in matrix [duplicate]

Just looking for a bit of direction, I realise that the example given is possible to solve using brute force iteration, but I am looking for a more elegant (ie. mathematical?) solution which could potentially solve significantly larger examples (say 20x20 or 30x30). It is entirely possible that this cannot be done, and I have had very little success in coming up with an approach which does not rely on brute force...
I have a matrix (call it A) which is nxn. I wish to select a subset (call it B) of points from matrix A. The subset will consist of n elements, where one and only one element is taken from each row and from each column of A. The output should provide a solution (B) such that the sum of the elements that make up B is the maximum possible value, given these constraints (eg. 25 in the example below). If multiple instances of B are found (ie. different solutions which give the same maximum sum) the solution for B which has the largest minimum element should be selected.
B could also be a selection matrix which is nxn, but where only the n desired elements are non-zero.
For example:
if A =
|5 4 3 2 1|
|4 3 2 1 5|
|3 2 1 5 4|
|2 1 5 4 3|
|1 5 4 3 2|
=> B would be
|5 5 5 5 5|
However, if A =
|5 4 3|
|4 3 2|
|3 2 1|
B =
|3 3 3|
As the minimum element of B is 3 which is larger than for
|5 3 1|
or
|4 4 1|
which also both sum to 9
Your problem is almost identical to the Assignment problem, which can e.g. be solved by the Hungarian algorithm in polynomial time.
Note that the assignment problem is usually a minimization problem, but multiplying your matrix with -1 and adding some constant should make the method applicable. Further, there is no formal tie-braking condition, for case of multiple optimal solutions. However, the method yields you a solution having the optimal sum. Let m be the minimum summand. Modify your matrix by setting all entries less or equal to m to zero and solve again. Either you get a solution with the same sum that is better than the last one. If not, the previous solution was already optimal.
As Matthias indicated you should use backtracking.
Find a reasonable solution. Select max values from each row and see if they are non-overlapping. If not, then perturb part of the solution so that the result becomes non-overlapping.
Define fitness of a partial solution. Let us say you are picking up value for each row iteratively and you have already picked values from first k rows. The fitness of this solution equals sum of the already picked values + max values from remaining rows and unselected columns
Now recursively start searching for solution. Select the values from first row, calculate their fitness and insert them into a priority queue. Remove all the solutions whose fitness is lower than the current optimal solution (initialized in step 1). Pick the solution at the head of the queue, calculate the next level of solutions and insert them back to the priority queue. Once you have selected values from all columns and rows, calculate the sum, and if it is higher than current optimal, replace it.
Ouch. This algorithm is wrong; there is no proof because it's wrong and therefore it's impossible to prove that it's correct. ;) I'm leaving it here because I'm too attached to delete it entirely, and it's a good demonstration of why you should formally prove algorithms instead of saying "this looks right! There's no possible way this could fail to work!"
I'm giving this solution without proof, for the time being. I have a proof sketch but I'm having trouble proving optimal substructure for this problem. Anyway...
Problem
Given a square array of numbers, select as many "non-overlapping" numbers as possible so that the sum of the selected numbers is maximised. "Non-overlapping" means that no two numbers can be from the same row or the same column.
Algorithm
Let A be a square array of n by n numbers.
Let Aij denote the element of A in the ith row and jth column.
Let S( i1:i2, j1:j2 ) denote the optimal sum of non-overlapping numbers for a square subarray of A containing the intersection of rows i1 to i2 and columns j1 to j2.
Then the optimal sum of non-overlapping numbers is denoted S( 1:n , 1:n ) and is given as follows:
S( 1:n , 1:n ) = max { [ S( 2:n , 2:n ) + A11 ]
[ S( 2:n , 1:n-1 ) + A1n ]
[ S( 1:n-1 , 2:n ) + An1 ]
[ S( 1:n-1 , 1:n-1 ) + Ann ] }
(recursively)
Note that S( i:i, j:j ) is simply Aij.
That is, the optimal sum for a square array of size n can be determined by separately computing the optimal sum for each of the four sub-arrays of size n-1, and then maximising the sum of the sub-array and the element that was "left out".
S for |# # # #|
|# # # #|
|# # # #|
|# # # #|
Is the best of the sums S for:
|# | | #| |# # # | | # # #|
| # # #| |# # # | |# # # | | # # #|
| # # #| |# # # | |# # # | | # # #|
| # # #| |# # # | | #| |# |
Implementation
The recursive algorithm above suggests a recursive solution:
def S(A,i1,i2,j1,j2):
if (i1 == i2) and (j1==j2):
return A[i1][j1]
else:
return max ( S( A, i1+1, i2, j1+1, j2) + A[i1][j1] ],
S( A, i1+1, i2, j1, j2-1) + A[i1][j2] ],
S( A, i1, i2-1, j1+1, j2) + A[i2][j1] ],
S( A, i1, i2-1, j1, j2-1) + A[i2][j2] ], )
Note that this will make O(4^n) calls to S()!! This is much better than the factorial O(n!) time complexity of the "brute force" solution, but still awful performance.
The important thing to note here is that many of the calls are repeated with the same parameters. For example, in solving a 3*3 array, each 2*2 array is solved many times.
This suggests two possible solutions for a speedup:
Make the recursive function S() cache results so that it only needs to S(A,i1,i2,j1,j2) once for each i1,i2,j1,j2. This means that S() only needs to calculate O(n^3) results - all other requests will be fufilled from cache. (This is called memoising.)
Instead of starting at the top, with the large n*n array, and working down through successively smaller subproblems, start at the bottom with the smallest possible subproblems and build up to the n*n case. This is called dynamic programming. This is also O(n^3), but it's a much faster O(n^3) because you don't have to hit a cache all the time.
The dynamic programming solution proceeds somewhat like:
Find optimal solutions to all 1x1 sub-arrays. (Trivial.)
Find optimal solutions for all 2x2 sub-arrays.
Find optimal solutions for all 3x3 sub-arrays.
...
Find optimal solutions for all n-1 * n-1 sub-arrays.
Find optimal solutions for the complete n*n sub-array.
Notes on this solution:
No proof yet. I'm working on it.
You'll note the algorithm above only gives you S(), the optimal sum. It doesn't tell you which numbers actually make up that sum. You get to add in your own method of backtracing your path to the solution.
The algorithm above doesn't guarantee the property that ties like 2,2 vs. 1,3 will be broken in favour of having all the individual numbers be as large as possible (so that 2,2 wins.) I believe you can define max() to break ties in favour of the largest numbers possible, and that will do what you want, but I can't prove it.
General notes:
Dynamic programming is a powerful technique for devising fast algorithms for any problem which exhibits two properties:
Optimal substructure: A problem can be broken down into slightly smaller parts, each of which can be used as part of the solution to the original problem.
Overlapping subproblems means that there are few actual subproblems to solve, and the solutions to the subproblems are re-used many times.
If the problem has optimal substructure, and the problem breaks down into slightly smaller problems - say a problem of size n breaks down into subproblems of size n-1 - then the problem can be solved by dynamic programming.
If you can split the problem into much smaller chunks - say chopping a problem of size n into halves, each of size n/2 - that's divide and conquer, not dynamic programming. Divide and conquer solutions are generally very fast - for example binary search will find an element in a sorted array in O(log n) time.
This is related to the n Queens problem, except that you do not care about the diagonal and you have weighted solutions. As the Queens problem, you can solve it by (multiple) backtracking.
I.e., once you find a solution you remember its weight, mark the soulution as invalid, and start over. The (a) solution with the highest weight wins.