Related
I am trying to read an input file and take only the single integers from the file and add them together and print the output to another file. The code I have works only if the file contains just single digit integers.
main :-
write('Name of input file ending with a period: '),
read(IN),
intsum(IN, 'numsum.txt').
intsum(IN, OUT) :-
see(IN),
tell(OUT),
get(X),
process(X,0,R),
write(R),
seen,
told.
process(-1, Y, Y).
process(X1,Y1,R1) :-
X1 < 48,
X1 > 57,
get(X3),
process(X3, Y1, R1). /* this line is what I am trying to use to check to see if the current value from the file is an integer */
process(X, Y, R) :-
X \= -1,
Y2 is Y + X - 48,
get(X2),
process(X2, Y2, R).`
The second process call is where I am trying to check to see if the current value read is and integer. I know that what is getting read from the input file is in ASCII when read. So I am checking to see if that value falls between the ASCII values for integers. If the value is not in ASCII value range for integers it will get the next input and check that one.
The third process call is checking for end of file and if not end of file and the read value is an integer then it will begin adding to the total.
The input.txt file contains: 1 2 b 3 4 c 5 and when the program is ran I get 116 as the output. I am looking for the result to be 15. When the file contains only: 1 2 3 4 5 the result is 15.
I am just struggling working out the kinks with making sure the value is an integer and if it is not one then just get the next value in the file.
Try this code:
intsum(In, Out) :-
see(In),
tell(Out),
intsum(0),
told,
seen.
intsum(S) :-
get_code(C),
( C = -1 % C is end of file
-> write(S)
; ( between(0'0, 0'9, C) % C is digit
-> S1 is S + C - 0'0
; S1 = S ), % C is not digit
intsum(S1) ).
Note that the conditional construct (Condition -> Then ; Else) avoids spurious choice points. The ASCII codes of the characters '0' and '9' can be represented, respectively, as 0'0 and 0'9. Predicate get/1 is deprecated and it is better to use predicate get_char/1. It is also recommended to use ISO compliant I/O instead of Edinburgh-style I/O.
So I have this mathematical language, it goes like this:
E -> number
[+,E,E,E] //e.g. [+,1,2,3] is 1+2+3 %we can put 2 to infinite Es here.
[-,E,E,E] //e.g. [-,1,2,3] is 1-2-3 %we can put 2 to infinite Es here.
[*,E,E,E] //e.g. [*,1,2,3] is 1*2*3 %we can put 2 to infinite Es here.
[^,E,E] //e.g. [^,2,3] is 2^3
[sin,E] //e.g. [sin,0] is sin 0
[cos,E] //e.g. [cos,0] is cos 0
and I want to write the set of rules that finds the numeric value of a mathematical expression written by this language in prolog.
I first wrote a function called "check", it checks to see if the list is written in a right way according to the language we have :
check1([]).
check1([L|Ls]):- number(L),check1(Ls).
check([L|Ls]):-atom(L),check1(Ls).
now I need to write the function "evaluate" that takes a list that is an expression written by this language, and a variable that is the numeric value corresponding to this language.
example:
?-evaluate([*,1,[^,2,2],[*,2,[+,[sin,0],5]]]],N) -> N = 40
so I wrote this:
sum([],0).
sum([L|Ls],N):- not(is_list(L)),sum(Ls,No),N is No + L.
min([],0).
min([L|Ls],N):-not(is_list(L)), min(Ls,No),N is No - L.
pro([],0).
pro([X],[X]).
pro([L|Ls],N):-not(is_list(L)), pro(Ls,No), N is No * L.
pow([L|Ls],N):-not(is_list(L)), N is L ^ Ls.
sin_(L,N):-not(is_list(L)), N is sin(L).
cos_(L,N):-not(is_list(L)), N is cos(L).
d([],0).
d([L|Ls],N):- L == '+' ,sum(Ls,N);
L == '-',min(Ls,N);
L == '*',pro(Ls,N);
L == '^',pow(Ls,N);
L == 'sin',sin_(Ls,N);
L == 'cos',cos_(Ls,N).
evaluate([],0).
evaluate([L|Ls],N):-
is_list(L) , check(L) , d(L,N),L is N,evaluate(Ls,N);
is_list(L), not(check(L)) , evaluate(Ls,N);
not(is_list(L)),not(is_list(Ls)),check([L|Ls]),d([L|Ls],N),
L is N,evaluate(Ls,N);
is_list(Ls),evaluate(Ls,N).
and it's working for just a list and returning the right answer , but not for multiple lists inside the main list, how should my code be?
The specification you work with looks like a production rule that describes that E (presumably short for Expression) might be a number or one of the 6 specified operations. That is the empty list [] is not an expression. So the fact
evaluate([],0).
should not be in your code. Your predicate sum/2 almost works the way you wrote it, except for the empty list and a list with a single element, that are not valid inputs according to your specification. But the predicates min/2 and pro/2 are not correct. Consider the following examples:
?- sum([1,2,3],X).
X = 6 % <- correct
?- sum([1],X).
X = 1 % <- incorrect
?- sum([],X).
X = 0 % <- incorrect
?- min([1,2,3],X).
X = -6 % <- incorrect
?- pro([1,2,3],X).
X = 6 ? ; % <- correct
X = 0 % <- incorrect
Mathematically speaking, addition and multiplication are associative but subtraction is not. In programming languages all three of these operations are usually left associative (see e.g. Operator associativity) to yield the mathematically correct result. That is, the sequence of subtractions in the above query would be calculated:
1-2-3 = (1-2)-3 = -4
The way you define a sequence of these operations resembles the following calculation:
[A,B,C]: ((0 op C) op B) op A
That works out fine for addition:
[1,2,3]: ((0 + 3) + 2) + 1 = 6
But it doesn't for subtraction:
[1,2,3]: ((0 - 3) - 2) - 1 = -6
And it is responsible for the second, incorrect solution when multiplying:
[1,2,3]: ((0 * 3) * 2) * 1 = 0
There are also some other issues with your code (see e.g. #lurker's comments), however, I won't go into further detail on that. Instead, I suggest a predicate that adheres closely to the specifying production rule. Since the grammar is describing expressions and you want to know the corresponding values, let's call it expr_val/2. Now let's describe top-down what an expression can be: It can be a number:
expr_val(X,X) :-
number(X).
It can be an arbitrarily long sequence of additions or subtractions or multiplications respectively. For the reasons above all three sequences should be evaluated in a left associative way. So it's tempting to use one rule for all of them:
expr_val([Op|Es],V) :-
sequenceoperator(Op), % Op is one of the 3 operations
exprseq_op_val(Es,Op,V). % V is the result of a sequence of Ops
The power function is given as a list with three elements, the first being ^ and the others being expressions. So that rule is pretty straightforward:
expr_val([^,E1,E2],V) :-
expr_val(E1,V1),
expr_val(E2,V2),
V is V1^V2.
The expressions for sine and cosine are both lists with two elements, the first being sin or cos and the second being an expression. Note that the argument of sin and cos is the angle in radians. If the second argument of the list yields the angle in radians you can use sin/1 and cos/2 as you did in your code. However, if you get the angle in degrees, you need to convert it to radians first. I include the latter case as an example, use the one that fits your application.
expr_val([sin,E],V) :-
expr_val(E,V1),
V is sin(V1*pi/180). % radians = degrees*pi/180
expr_val([cos,E],V) :-
expr_val(E,V1),
V is cos(V1*pi/180). % radians = degrees*pi/180
For the second rule of expr_val/2 you need to define the three possible sequence operators:
sequenceoperator(+).
sequenceoperator(-).
sequenceoperator(*).
And subsequently the predicate exprseq_op_val/3. As the leading operator has already been removed from the list in expr_val/2, the list has to have at least two elements according to your specification. In order to evaluate the sequence in a left associative way the value of the head of the list is passed as an accumulator to another predicate exprseq_op_val_/4
exprseq_op_val([E1,E2|Es],Op,V) :-
expr_val(E1,V1),
exprseq_op_val_([E2|Es],Op,V,V1).
that is describing the actual evaluation. There are basically two cases: If the list is empty then, regardless of the operator, the accumulator holds the result. Otherwise the list has at least one element. In that case another predicate, op_val_args/4, delivers the result of the respective operation (Acc1) that is then recursively passed as an accumulator to exprseq_op_val_/4 alongside with the tail of the list (Es):
exprseq_op_val_([],_Op,V,V).
exprseq_op_val_([E1|Es],Op,V,Acc0) :-
expr_val(E1,V1),
op_val_args(Op,Acc1,Acc0,V1),
exprseq_op_val_(Es,Op,V,Acc1).
At last you have to define op_val_args/4, that is again pretty straightforward:
op_val_args(+,V,V1,V2) :-
V is V1+V2.
op_val_args(-,V,V1,V2) :-
V is V1-V2.
op_val_args(*,V,V1,V2) :-
V is V1*V2.
Now let's see how this works. First your example query:
?- expr_val([*,1,[^,2,2],[*,2,[+,[sin,0],5]]],V).
V = 40.0 ? ;
no
The simplest expression according to your specification is a number:
?- expr_val(-3.14,V).
V = -3.14 ? ;
no
The empty list is not an expression:
?- expr_val([],V).
no
The operators +, - and * need at least 2 arguments:
?- expr_val([-],V).
no
?- expr_val([+,1],V).
no
?- expr_val([*,1,2],V).
V = 2 ? ;
no
?- expr_val([-,1,2,3],V).
V = -4 ? ;
no
The power function has exactly two arguments:
?- expr_val([^,1,2,3],V).
no
?- expr_val([^,2,3],V).
V = 8 ? ;
no
?- expr_val([^,2],V).
no
?- expr_val([^],V).
no
And so on...
I want to create a program in Fortran that multiplies vectors from a .dat file that has the following format:
x1 y1 z1
x2 y2 z2
The index 1 and 2 refer to the vector 1 and 2, respectively. First I want do identify the vectors, so far I have
program ex2
implicit none
real*8 x
integer i
write(6,*) "Insert the vectors from vet_in.dat"
open (10, file ="vet_in.dat")
read (10,*) x(i), i=1,3
end program ex2
The line of the read(10,*) was sugested to me, I don't quite get it, I thought fortran identified the ij matrix index. And then I wanted to multiply x1.x2, y1.y2 and z1.z2, maybe the loop and de if could be used. Can you help me to proceed?
First, you need to declare x and also y as an array of rank 1 and size 3:
real*8 x(3), y(3)
And also a scalar variable for the result
real*8 result
Don't write to unit 6, but use *:
write(*,*) "Insert..."
but I wouldn't write anything at all.
Now you can read the vectors. If they are stored in rows you can read them in one go
read(10,*) x
or
read(10,*) (x(i), i=1, 3)
(read about implied do in any textbook).
and then the same for y.
Then you can make a scalar product of them:
result = dot_product(x, y)
(see https://gcc.gnu.org/onlinedocs/gfortran/DOT_005fPRODUCT.html)
or
result = sum(x*y)
or
result = 0
do i = 1, 3
result = result + x(i) * y(i)
end do
Note that real*8 is not legal standard Fortran, just a non-standard extension. You can use double precision instead until you learn kinds.
I want to implement a predicate (vecLine2BitLine) which does the following:
get two lists and a number the first list is the length of blocks (the elements of the blocks are '$') and the second list contains the indexes that these blocks should be placed at meaning:
vecLine2BitLine([1,2,1],[2,5,9],12,BitLine).
BitLine=[' ','$',' ',' ','$','$',' ',' ','$',' ',' ',' '].
explanation:a block of length 1 is at index 2
and a block of length 2 is at index 5 and so on..
insert_at_mul : inserts an element N times (it works perfectly,dupli and my_flatten were implemented previously so i used them)
Ive been trying to activate insert_at_mul N times when N is the length of the list X and Y
in the predicate vecLine2BitLine.
dupli(L1,N,L2) :- dupli(L1,N,L2,N).
dupli([],_,[],_).
dupli([_|Xs],N,Ys,0) :- dupli(Xs,N,Ys,N).
dupli([X|Xs],N,[X|Ys],K) :- K > 0, K1 is K - 1, dupli([X|Xs],N,Ys,K1).
my_flatten(X,[X]) :- \+ is_list(X).
my_flatten([],[]).
my_flatten([X|Xs],Zs) :- my_flatten(X,Y), my_flatten(Xs,Ys), append(Y,Ys,Zs).
insert_at_mul(L,X,K,R,N):-dupli([X],N,XX) , insert_at(L,XX,K,L1) , my_flatten(L1,R).
get_num_spaces(L,N,X):-sum(L,S), X is N-S.
generate_spaces(N,L,X):- insert_at_mul(L,'',1,X,N).
vecLine2BitLineAux([],[],_,_,_).
vecLine2BitLineAux([X|Tail1],[Y|Tail2],N,L,Lnew):- insert_at_mul(L,'*',Y,Lnew,X) ,vecLine2BitLineAux(Tail1,Tail2,N,Lnew,R). // problem here!!!
vecLine2BitLine(X,Y,N,L):- get_num_spaces(X,N,Z) , generate_spaces(Z,[],ZZ) , vecLine2BitLineAux(X,Y,N,ZZ,L).
now the problem is that in the function vecLine2BitLine i cant activate insert_at_mul N times(thats what i tried to do in this code, but failed).
how can I fix vecLine2BitLine for it to work properly as in returning the correct output by actually activating the predicate insert_at_mul N times??
THANKS!
added :
vecLine2BitLine : input parameters : (L1,L2,N,Result)
N: after activating the predicate Result will be N in length.
L1: L1 is a list of numbers each number indicates the length of a block, a block is comprised of a Sequence of '$'.
L2: L2 is a list of numbers the numbers are indices for where the blocks in L1 should be placed.
example:
vecLine2BitLine([3,2],[1,5],9,BitLine).
we can look at the input better as tuples :
vecLine2BitLine[(3,1),(2,5)],9,BitLine).
(3,1) : there is a sequence of '' 3 times at index 1
(2,5) : there is a sequence of '' 2 times at index 5
in our example 9 is the length of BitLine at the end and we have to insert into the
list BitLine 3+2 of the "special chars" '*' but we have 9-(3+2) places left in the list
so we add '' in those places and then we get:
BitLine=['$','$','$','','$','$','','','',''].
This is kind of a nice problem because you can use the arguments as loop counters. The K argument gets you to the proper index. Let's just traverse the list and find a particular index as an example. Notice the base case is that you're at the right element, and the inductive case is prior to the right element.
traverse(1, [X|_], X).
traverse(N, [_|Xs], X) :- N > 0, N0 is N-1, traverse(N0, Xs, X).
We're going to apply that pattern to insert_at/4 to get to the right location in the list. Now let's write a repeat/3 predicate that repeats X N times in a new list L. This time the base case is when we've added all the repetitions we care to, and the inductive case is that we'll add another instance.
repeat(1, X, [X]).
repeat(N, X, [X|Xs]) :- N > 0, N0 is N-1, repeat(N0, X, Xs).
You can see the similarity of structure between these two. Try to combine them into a single predicate. Since this is homework, I'll stop here. You're inches from the goal.
I have been trying to learn Erlang and have been running into some problems with ending lines in functions and case statements.
When do I use a semicolon (;), comma (,), or period inside my functions or case statements?
I like to read semicolon as OR, comma as AND, full stop as END. So
foo(X) when X > 0; X < 7 ->
Y = X * 2,
case Y of
12 -> bar;
_ -> ook
end;
foo(0) -> zero.
reads as
foo(X) when X > 0 *OR* X < 7 ->
Y = X * 2 *AND*
case Y of
12 -> bar *OR*
_ -> ok
end *OR*
foo(0) -> zero *END*
This should make it clear why there is no ; after the last clause of a case.
Comma at the end of a line of normal code.
Semicolon at the end of case statement, or if statement, etc.
The last case or if statement doesn't have anything at the end.
A period at the end of a function.
example (sorry for the random variable names, clearly this doesn't do anything, but illustrates a point):
case Something of
ok ->
R = 1, %% comma, end of a line inside a case
T = 2; %% semi colon, end of a case, but not the end of the last
error ->
P = 1, %% comma, end of a line inside a case
M = 2 %% nothing, end of the last case
end. %% period, assuming this is the end of the function, comma if not the end of the function
Period (.)
In modules, the period is used to terminate module attributes and function declarations (a.k.a. 'forms'). You can remember this because forms aren't expressions (no value is returned from them), and therefore the period represents the end of a statement.
Keep in mind that definitions of functions with different arities are considered separate statements, so each would be terminated by a period.
For example, the function definitions for hello/0 and hello/1:
hello() -> hello_world.
hello(Greeting) -> Greeting.
(Note that in the erlang shell the period is used to terminate and evaluate expressions, but that is an anomaly.)
Semicolon (;)
The semicolon acts as a clause separator, both for function clauses and expression branches.
Example 1, function clauses:
factorial(0) -> 1;
factorial(N) -> N * fac(N-1).
Example 2, expression branches:
if X < 0 -> negative;
X > 0 -> positive;
X == 0 -> zero
end
Comma (,)
The comma is an expression separator. If a comma follows an expression, it means there's another expression after it in the clause.
hello(Greeting, Name) ->
FullGreeting = Greeting ++ ", " ++ Name,
FullGreeting.
You can think of it like english punctuation. Commas are used to separate things in a series, semicolons are used to separate two very closely related independent clauses[1] (e.g. the different cases of the case statement, function clauses of the same name and arity that match different patterns), and periods are used to end a sentence (complete thought).
Or to prove you went to college. "Do not use semicolons. They are transvestite hermaphrodites representing absolutely nothing. All they do is show you've been to college." -- Kurt Vonnegut
The comma separates expressions, or arguments, or elements of a list/tuple or binary. It is overworked.