ISBN-13 digit check using Haskell - list

I just started functional programming, using Haskell, and I want to write a short function that checks a 13-digit code and checks if it is an ISBN number.
The formula for the check is:
x13 = (10 − ((x1 + 3x2 +x3 + 3x4 +x5 + 3x6 +x7 + 3x8 +x9 + 3x10 +x11 + 3x12)%10))%10
(x1 being the first digit, x2 the second, ..., x13 the last digit etc.)
I want the input to be a list so it's easier for me (13 integers, each 0-9).
So something like this (stuff below is simplified):
isValid :: [Int] -> Bool
--isValid = True if (lastdigit = formula) -- can this be done in one (long) line?
So, for example:
isValid [ 9, 7, 8, 0, 1, 3, 7, 0, 5, 3, 4, 6, 9 ]
should return True
I've been trying to do this for a few hours but I'm not good enough at Haskell yet and it's confusing me. Can someone point me in the right direction? I don't know much about Haskell, which is the main problem.

You can just pattern match on a list of 13 elements, like:
isValid :: [Int] -> Bool
isValid [x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13] = …
isValid _ = False
with … the part you still need to fill in. Hint: you can use mod :: Integral a => a -> a -> a to calculate a modulo (in some programming languages that is done with %).
Here x13 is thus the last digit that you can use in the check.

Related

Adding constrain to check if there exist a combination of pairs such that it statisfy a ratio?

Lets say I have a set of items in a set x0, ..., x14 each consisting its own values v0, ..., v14
I am trying to at most 8 items such that I get the maximum value.
I am able to get the following maximization problem
max v0*x0 + ... + v14*x14
s.t.
x0 + ... + x14 <= 8
0 <= x0 <= 1
.
.
0 <= x14 <= 1
However, I need to add another constrains, that is for the items chosen, I should be able to pair them such that their ratio is less than 2.
i.e. lets say that the item chosen is x0, x1, x3, x4, x8, x9, x10, x11 with the maximum value they would also have a configuration of pairing such that,
(v0 * x0)/(v1 * x1) <= 2,
(v3 * x3)/(v9 * x9) <= 2,
(v4 * x4)/(v11 * x11)<= 2,
(v8 * x8)/(v10 * x10)<= 2,
Any idea on how to formulate the above set of constrains?
So you can precompute the valid pairs, and their value (the sum of the 2 elements)
So there are at most 14 * 13 / 2 potential ordered pairs, much less valid ones.
You need to select 4 pairs subject to the constraint that once a pair is selected, any pairs involving the same elements cannot be selected. This is a simple at most one constraints on 14 subsets of pairs.
for all item in items:
sum(bool_pair for all bool_pair involving item) <= 1
You can use CP-SAT or the linear solver wrapper to solve this.

Padding an array with zeroes in fortran without using loops

I have two arrays, and I want to compare their sizes and add trailing zeroes to whichever array is shorter.
eg- For arrays -
y1=(/ 1,2,3 /)
y2=(/ 1,2,3,4,5 /)
The final result should be -
y1=(/ 1,2,3,0,0 /)
y2=(/ 1,2,3,4,5 /)
I am very new to Fortran, and from what I know till now, this can be done like this:-
integer, allocatable :: y1(:),y2(:)
integer :: l1,l2,i
.
.
.
! some code to generate y1 and y2 here
.
.
.
l1=size(y1)
l2=size(y2)
if (l1>l2) then
do i=l2+1,l1
y2(i)=0
enddo
else if (l2>l1) then
do i=l1+1,l2
y1(i)=0
enddo
endif
I want to know if there is a better way of doing this, preferably one that doesn't involve loops, since the actual problem I am working on might have huge vectors
Here's one way:
y1 = RESHAPE(y1,SHAPE(y2),pad=[0])
No explicit loops. As #VladimirF commented the shorter array has to be re-allocated, this approach leaves it to the compiler and the run-time to take care of that.
If you are concerned about the performance of this approach, or concerned about its performance wrt a version using explicit loops, and concerned about how the performance scales with the sizes of arrays, then run some tests. I wouldn't be surprised to find that explicit reallocation and a loop or two are faster than this 'clever' approach.
If you are only concerned with rank 1 arrays, using SHAPE and RESHAPE is overkill. Simply use Fortran's array constructor features. You also can use modern Fortran's allocation-on-assignment feature, so you do not need to re-allocate the shorter array.
program foo
implicit none
integer, allocatable :: y1(:),y2(:)
integer :: l1,l2,i
y1 = [1, 2, 3]
y2 = [1, 2, 3, 4, 5]
l1 = size(y1)
l2 = size(y2)
if (l1 > l2) y2 = [y2, [(0,i=1,l1-l2)]]
if (l2 > l1) y1 = [y1, [(0,i=1,l2-l1)]]
print '(10(I0,1X))', y1
print '(10(I0,1X))', y2
end program foo

Simple Arithmetic Constraint on List ECLiPSe clp

I want to do a simple constraint over all values of a list,
I want each index of each row of an array to have the following (ic) constraint:
500 #= 2^X1 + 2^X2 + 2^X3 + ... + 2^X9
I try to do the code below. Array is a 9x9 matrix and for every row I want the above constraint to be satisfied. However, this does not seem to work, the program does not find any possible values that satisfy the constraint.
model(Array) :-
Array :: 1..9,
(for(I,1,9), param(Array)
do
X1 is Array[I,1],
X2 is Array(I,2],
X3 is Array[I,3],
X4 is Array[I,4],
X5 is Array[I,5],
X6 is Array[I,6],
X7 is Array[I,7],
X8 is Array[I,8],
X9 is Array[I,9],
500 #= 2^X1 + 2^X2 + 2^X3 + 2^X4 + 2^X5 + 2x^X6 + 2^X7 + 2^X8 + 2^X9
),
term_variables(Array,L),
labeling(L),
printBoard(Array).
This seems to be a bug in the implementation of integer constraints involving exponentiation expressions. Since your variables are all integral anyway, you can replace the #= with $= and it will work (the # constraints are supposed to impose integrality on the variables, while the $ constraints don't do this).
By the way, you could shorten your code this way:
...,
( foreacharg(Row,Array) do
( foreacharg(X,Row), foreach(2^X,Powers) do true ),
500 $= sum(Powers)
),
...

Advanced comparison of lists

I am currently making a program for a school project which is supposed to help farmers overfertilize less (this is kind of a big deal in Denmark). The way the program is supposed to work is that you enter some information about your fields(content of NPK, field size, type of dirt and other things), and then i'll be able to compare their field's content of nutrition to the recommended amount. Then I can create the theoretical ideal composition of fertilizer for this field.
This much I have been able to do, but here is the hard part.
I have a long list of fertilizers that are available in Denmark, and I want my program to compare 10 of them to my theoretical ideal composition, and then automatically pick the one that fits best.
I literally have no idea how to do this!
The way I format my fertilizer compositions is in lists like this
>>>print(idealfertilizercomp)
[43.15177154944473, 3.9661554732945534, 43.62771020624008, 4.230565838180857, 5.023796932839768]
Each number represent one element in percent. An example could be the first number, 43.15177154944473, which is the amount of potassium I want in my fertilizer in percent.
TL;DR:
How do I make a program or function that can compare a one list of integers to a handfull other lists of integers, and then pick the one that fits best?
So, while i had dinner i actually came up with a way to compare multiple lists in proportion to another:
def numeric(x):
if x >= 0:
return x
else:
return -x
def comparelists(x,y):
z1 = numeric(x[0]-y[0])
z2 = numeric(x[1]-y[1])
z3 = numeric(x[2]-y[2])
z4 = numeric(x[3]-y[3])
z5 = numeric(x[4]-y[4])
zt = z1+z2+z3+z4+z5
return zt
def compare2inproportion(x, y, z):
n1 = (comparelists(x, y))
n2 = (comparelists(x, z))
print(n1)
print(n2)
if n1 < n2:
print(y, "is closer to", x, "than", z)
elif n1 > n2:
print(z, "is closer to", x, "than", y)
else:
print("Both", y, "and", z, "are equally close to", x)
idealfertilizer = [1, 2, 3, 4, 5]
fertilizer1 = [2, 3, 4, 5, 6]
fertilizer2 = [5, 4, 3, 2, 1]
compare2inproportion(idealfertilizer, fertilizer1, fertilizer2)
This is just a basic version that compares two lists, but its really easy to expand upon. The output looks like this:
[2, 3, 4, 5, 6] is closer to [1, 2, 3, 4, 5] than [5, 4, 3, 2, 1]
Sorry for taking your time, and thanks for the help.

Do loop with 2 variables changing in each step of loop

I'm working on Fortran 90. I need to calculate a recursion like xn = 6*(xn-1) + 7*(xn-2) where (xn-1) is the n-1 step and (xn-2) is the n-2 step. So if we set x1 = 2 and x0 = 1 we get x2 = 6*x1 + 7*x0 and so on for each n.
So I wrote
x0 = 1.
x1 = 2.
do i = 1,20
xn = 6.*x1 + 7.*x0
x1 = xn
x0 = x1
end do
but this code is replacing x0 and x1 for xn and I need to replace x1 for xn and x0 for x1 in each step. I'd tryed many things but I failed. Any idea how to do that?
Though the answer has already been added to this question, let me answer a more general question which is encountered more frequently. Consider the problem where the very next value in the iteration depends on n previous values. In the present case n = 2. The general strategy to solve this problem is to construct another 1-d array of size n and save all the initial values x(1),x(2),..,x(n) in this array. Then in each iteration we use these values to calculate the next value x(n+1) and update the array with x(1) by x(2), x(2) by x(3),...,x(n) by x(n+1) and again use these values to calculate the next value of x and so on. A particular example where such strategy must necessarily be used is the integration of time-delayed systems.
#parthian-shot has given the correct answer in the comment. But that leaves the question marked as unanswered, so I am repeating it here:
You are assigning the value of xn to x1, and then the value of x1 (which is now the same as xn) to x0. You just need to flip it around:
do i = 1,20
xn = 6.*x1 + 7.*x0
x0 = x1
x1 = xn
end do