Smallest distance in a list to the number 0 supplies amount of that number with map - dictionary

I want to create a function absmin which gets a list of floating point numbers and returns the amount of that number which has the smallest distance to 0.
We should do it with the function map. My first idea was that the function abs mentioned the problem with amount, but know my question is, how it is possible to create the point with the smallest distance to 0 and that with the map function, can somebody help me?
absmin :: [Double] -> Int
absmin [] = []
absmin (x:xs) = abs (map (x:xs))
Okay, now i changed to:
absmin xs = map abs xs
But with the specification: absmin :: [Double] -> Double it didn't work, maybe i´m to stupid, but i try and try and it didn't work

If you have a list like [3.14, 2.98, -0.1] and need to find which number is closest to zero, you need to first map abs to that list, and then you need to find the min.
Now min has signature Ord a => a -> a -> a so it only considers two numbers at the same time. Fortunately we can use a fold to fold this function over our list.
Prelude> absmin = foldr1 min . map abs
Prelude> absmin [3.14, 2.98, -0.1]
0.1
The problem with this is that we don't know if the closest number to zero was 0.1 or -0.1.
So let's map each element to a tuple containing its absolute value and the original value. We can define a minBy function that lets us find the minimum of two values based on a function like fst.
After we've folded this function over the list of tuples, we just need to call snd on the result to get the original value.
Prelude> :{
Prelude| minBy f a b
Prelude| | f a <= f b = a
Prelude| | otherwise = b
Prelude| :}
Prelude> absmin' = snd . foldr1 (minBy fst) . map (\x -> (abs x, x))
Prelude> absmin' [3.14, 2.98, -0.1, 0.1]
-0.1

You can use the min() and abs() functions to find the smallest absolute value in a list of numbers, and then use map() to apply this value to each element in the list.

Related

How do I check if the path from a node to another has a depth equal to a given one in a graph in OCaml?

First of all, I'm sorry for how I wrote my question.
Anyway, I'm trying to write a function in OCaml that, given a graph, a max depth, a starting node, and another node, returns the list of the nodes that make the path but only if the depth of it is equal to the given one. However, I can't implement the depth part.
This is what I did:
let m = [(1, 2, "A"); (2, 3, "A");
(3, 1, "A"); (2, 4, "B");
(4, 5, "B"); (4, 6, "C");
(6, 3, "C"); (5, 7, "D");
(6, 7, "D")]
let rec vicini n = function
[] -> []
| (x, y, _)::rest ->
if x = n then y :: vicini n rest
else if y = n then x :: vicini n rest
else vicini n rest
exception NotFound
let raggiungi m maxc start goal =
let rec from_node visited n =
if List.mem n visited then raise NotFound
else if n = goal then [n]
else n :: from_list (n :: visited) (vicini n m)
and from_list visited = function
[] -> raise NotFound
| n::rest ->
try from_node visited n
with NotFound -> from_list visited rest
in start :: from_list [] (vicini start m)
I know I have to add another parameter that increases with every recursion and then check if its the same as the given one, but I don't know where
I am not going to solve your homework, but I will try to teach you how to use recursion.
In programming, especially functional programming, we use recursion to express iteration. In an iterative procedure, there are things that change with each step and things that remain the same on each step. An iteration is well-founded if it has an end, i.e., at some point in time, the thing that changes reaches its foundation and stops. The thing that changes on each step, is usually called an induction variable as the tribute to the mathematical induction. In mathematical induction, we take a complex construct and deconstruct it step by step. For example, consider how we induct over a list to understand its length,
let rec length xs = match xs with
| [] -> 0
| _ :: xs -> 1 + length xs
Since the list is defined inductively, i.e., a list is either an empty list [] or a pair of an element x and a list, x :: list called a cons. So to discover how many elements in the list we follow its recursive definition, and deconstruct it step by step until we reach the foundation, which is, in our case, the empty list.
In the example above, our inductive variable was the list and we didn't introduce any variable that will represent the length itself. We used the program stack to store the length of the list, which resulted in an algorithm that consumes memory equivalent to the size of the list to compute its length. Doesn't sound very efficient, so we can try to devise another version that will use a variable passed to the function, which will track the length of the list, let's call it cnt,
let rec length cnt xs = match xs with
| [] -> cnt
| _ :: xs -> length (cnt+1) xs
Notice, how on each step we deconstruct the list and increment the cnt variable. Here, call to the length (cnt+1) xs is the same as you would see in an English-language explanation of an algorithm that will state something like, increment cnt by one, set xs to the tail xs and goto step 1. The only difference with the imperative implementation is that we use arguments of a function and change them on each call, instead of changing them in place.
As the final example, let's devise a function that checks that there's a letter in the first n letters in the word, which is represented as a list of characters. In this function, we have two parameters, both are inductive (note that a natural number is also an inductive type that is defined much like a list, i.e., a number is zero or the successor of a number). Our recursion is also well-founded, in fact, it even has two foundations, the 0 length and the empty list, whatever comes first. It also has a parameter that doesn't change.
let rec has_letter_in_prefix letter length input =
length > 0 && match input with
| [] -> false
| char :: input ->
char = letter || has_letter_in_prefix letter (length-1) input
I hope that this will help you in understanding how to encode iterations with recursion.

Sum, Average of elements and Count the occurence of elements in Lists in Prolog

how can I write three predicates in Prolog that do the following things:
1) Define the sum (X, N) predicate, which is true when N is the sum of integers from the list X.
2) Define the avg (X, N) predicate that calculates the arithmetic average of all elements of the list X, where N is the number of elements.
3) Define the predicate called count(X, Y, N), which is true if the list Y contains N element instances
X.
Could you give me the examples of them and explain to me why they work the way they do? I know there are dozens of sum and avg predicates here on Stack Overflow, but I can't really understand why they work.
Define the sum(X, N) predicate, which is true when N is the sum of integers from the list X.
You want to calculate the sum of the elements of a list. What would be the simplest instance of the problem? When the list is empty, the sum of its element is 0. How can we break down larger lists to get to the simple case? We can remove the first element of the list, calculate the sum of the remaining list, and then add the first element to the result.
This approach can be implemented with the following code:
% Simple case: Sum of the empty list
sum([], 0).
% Recursive case: Split list into first element X and remaining list XS
sum([X|XS], N) :- sum(XS, M), N is M + X.
Usage:
?- sum([1,2,3],6).
true.
?- sum([1,2,3],X).
X = 6.
The is operator does arithmetic evaluation of its right-hand side (reference), as opposed to treating M + X as a literal term. If you would use = instead of is, M + X would be treated as a literal term. You would then get the following output:
?- sum([1,2,3],6).
false.
?- sum([1,2,3],0+3+2+1).
true.
So for Prolog 6 and 0+3+2+1 are different terms, until you force arithmetic evaluation as done by is.
2) Define the avg (X, N) predicate that calculates the arithmetic average of all elements of the list X, where N is the number of elements.
This is not possible. If X is the list and N the number of elements, then the predicate has no way of outputting the average (unless you count printing the average as a side-effect, I don't think you want). To fix this, add another parameter A that represents the average: avg(X, N, A).
We can calculate the average by taking the sum of the list and dividing it by the length of the list:
avg(X, N, A) :- sum(X, S), length(X, N), A is S / N.
Usage:
?- avg([1,2,3],3,2).
true.
?- avg([1,2,3,4],N,X).
N = 4,
X = 2.5.
3) Define the predicate called count(X, Y, N), which is true if the list Y contains N element instances X.
I understand you want N to be the number of times that the number X occurs in the list Y. We can again break this down into a simple case and then try to break down the general case into smaller steps until we get to the simple case.
For an empty list, we know that X occurs zero times in that list. For a non-empty list, we can remove the first element and check of how often X occurs in the remaining list. If the first element if equal to X, then the total number of occurrences of X is one plus the number of occurrences in the remaining list. If the first element is not equal to X, then the total number of occurrences of X is equal to the number of occurrences in the remaining list.
This approach can be implemented with the following code:
% Simple case: The list is empty.
count(_, [], 0).
% Recursive case: First element is equal to X
count(X, [X|YS], N) :- count(X, YS, M), N is M + 1, !.
% Recursive case: First element is unequal to X
count(X, [Y|YS], N) :- X \= Y, count(X, YS, N).
We use _ for variables we do not care about. We could also write X instead of _, but Prolog would then give us a warning about an unused variable.
Usage:
?- count(1, [1,1,2,3], N).
N = 2.
?- count(2, [1,1,2,3], N).
N = 1.

Prolog query fails

This is supposed to calculate the sum of two lists. The lists can be of different size.
sum([],[],[]).
sum(A,[],A).
sum([],B,B).
sum([A|Int1],[B|Int2],[C|Int3]) :-
(
C =:= A + B
;
((C =:= A), B = [])
;
((C =:= B), A = [])
),
sum(Int1,Int2,Int3).
It seems to work correctly, except when trying to find the sum of two lists. Then it gives the following error:
ERROR: =:=/2: Arguments are not sufficiently instantiated
I don't see why. There's a recursive and a basis step, what exactly is not yet instantiated and how do I fix it?
[1] While your disjunctions in the last clause are -- to some extent -- conceptually correct, Prolog considers these disjunctions in sequence. So it first considers C =:= A + B. But either A or B can be the empty list! This is what causes the error you reported, since the empty list is not allowed to occur in a numeric operation.
[2] You need to use C is A + b (assignment) i.o. C =:= A + B (numeric equivalence).
[3] If you say [A|Int1] and then A = [], then this means that [A|Int1] is not (only) a list of integers (as you claim it is) but (also) a list of lists! You probably intend to check whether the first or the second list is empty, not whether either contains the empty list.
Staying close to your original program, I would suggest to reorder and change things in the following way:
sumOf([], [], []):- !.
sumOf([], [B|Bs], [C|Cs]):- !,
C is B,
sumOf([], Bs, Cs).
sumOf([A|As], [], [C|Cs]):- !,
C is A,
sumOf(As, [], Cs).
sumOf([A|As], [B|Bs], [C|Cs]):-
C is A + B,
sumOf(As, Bs, Cs).
For example:
?- sumOf([1,2,3], [1,-90], X).
X = [2, -88, 3]
Notice my use of the cut (symbol !) in the above. This makes sure that the same answer is not given multiple times or -- more technically -- that no choicepoints are kept (and is called determinism).
You should read a tutorial or a book. Anyway, this is how you add two things to each other:
Result is A + B
This is how you could add all elements of one list:
sum([], 0). % because the sum of nothing is zero
sum([X|Xs], Sum) :-
sum(Xs, Sum0),
Sum is X + Sum0.
And this is how you could add the sums of a list of lists:
sums([], 0).
sums([L|Ls], Sums) :-
sums(Ls, Sums0),
sum(L, S),
Sums is Sums0 + S.

Isabelle: maximum value in a vector

I would like to find the maximum in a vector of natural numbers. Vector (i.e., ‘vec’), however, is a different type than Set or List. I thought about several ideas that did not work, like leveling or lifting the type of vec or the definition of a recursive function.
What solution do you suggest to get the maximum value in a vector?
(*
IMPORTS:
"~~/src/HOL/Algebra/Ring"
"~~/src/HOL/Library/Numeral_Type"
"~~/src/HOL/Library/Permutations"
"~~/src/HOL/Library/Polynomial"
"~~/src/HOL/Big_Operators"
vec (VECTOR) is from Finite_Cartesian_Product
degree is from Polynomial
Max is from Big_Operators
*)
(* The problem is that "Max" from Big_Operators is not working on vectors! *)
definition maxdeg:: "('a::zero poly)^'n ⇒ nat" where "maxdeg v = Max(χ i . degree(v$i))"
The maximum operator Max has type 'a set => 'a, i.e., retrieves the maximum element from a (finite) set. Vectors (type (a, b) vec) are essentially functions from indices to entries with abstraction written as χ i. _ and application as v $ _.
You now want to get the maximum value in the range of a vector. With the above in mind, you can use the range function and spell out the function application on vectors:
maxdeg v = Max (range (%j. (χ i. degree (v $ i)) $ j))
This can be simplified to
maxdeg v = Max (range (%i. degree (v $ i)))
If you just want the maximum entry of a vector without mapping degree over vector first, the following works (where op $ v is the eta-contraction of %j. v $ j):
maxvec v = Max (range (op $ v))

Recursive Data types in sml

Is there a way define a datatype for whole numbers. i.e. 0,1,2,... not zero, one ,... individually.
I want to define the set of whole numbers. bu using 0, n,n+1 with recursion.
I tried something like this: datatype nat=0|n|n+1 . But it was nearly obvious not to work because it does not recognize 0 as integer right?
I would appreciate any help.
Since the set of natural numbers is countably infinite, you can't enumerate all the cases.
You can represent natural numbers conceptually by Peano numbers:
datatype peano = Zero | Succ of peano
The datatype is very simple, it only defines 0 and ensures that each natural number has a successor. For example, 2 is actually represented as Succ (Succ Zero).
fun count Zero = 0
| count (Succ p) = 1 + count p
Use similar techniques, you can build up add, sub, mult functions like you have with natural numbers.

Resources