I'm new to prolog and i can't find a solution to filter list by 2 conditions, save result into 2 variables and then evaluate answer base on them.
In my case, if list contains more numbers that greater then 0, then numbers lesser then 0.
For example i get a list with elements:
checklist([-2, 3.3, 12, -10.1, 14, -11, 123]) # true
checklist([-2.1, -3, -4, 14, 16.7]) # false
checklist([11.5, 2.5, -34.1, -1]) # false
I'd write something like this in python:
bigger_count = 0
lesser_count = 0
for num in list:
if num > 0:
bigger_count += 1
elif num < 0:
lesser_count += 1
print(bigger_count > lesser_count)
Especially i doesn't understand how to work with 2 variables at one time.
https://www.swi-prolog.org/pldoc/doc_for?object=include/3
https://www.swi-prolog.org/pldoc/doc_for?object=convlist/3
If you have 2 conditions, you need to traverse the list twice, but is the complexity of code that can handle two different predicates worth the trouble?
Anyway, if you're writing from scratch, you can simplify your life by using DCGs:
filter(_Pred, []) --> [].
filter(Pred, [X|Xs]) -->
( { call(Pred, X) }
-> [X]
; []
),
filter(Pred, Xs).
filter(Pred, List, Result) :-
phrase(filter(Pred, List), Result).
even(X) :- 0 is X mod 2.
?- filter(even, [1,2,3,4,5], X).
X = [2, 4]
Another possible solution is:
check(List) :-
check(List, Balance),
Balance > 0.
check([], 0).
check([X|Xs], B) :-
check(Xs, B0),
( X > 0 -> B is B0 + 1
; X < 0 -> B is B0 - 1
; B is B0 ).
Examples:
?- check([-2, 3.3, 12, -10.1, 14, -11, 123]).
true.
?- check([-2.1, -3, -4, 14, 16.7]).
false.
?- check([11.5, 2.5, -34.1, -1]).
false.
?- check([1,-1]).
false.
The easiest way is to use a worker predicate that carries the required extra state.
checklist( Ns, P, N ) :- checklist(Ns, 0, 0, P, N )
checklist( [] , P , N , P , N ) .
checklist( [X|Xs] , P0 , N0 , P , N ) :- X > 0, P1 is P0+1, checklist(Xs,P1,N0,P,N).
checklist( [X|Xs] , P0 , N0 , P , N ) :- X < 0, B1 is N0+1, checklist(Xs,P0,N1,P,N).
If you add up all the values in the list, you'll get a positive or negative result which varies with how big the numbers are, instead of how many there are. There is a mathematical function sign or signum which turns all negative values into -1, and all positive values into +1, then you can add them up and if there were more positive inputs, the answer is positive, if there are more negative inputs, the answer is negative. Or they will cancel out and the sum will be 0.
If you maplist signthat over the inputs:
?- maplist(sign, [-2, 3.3, 12, -10.1, 14, -11, 123], X).
X = [-1, 1.0, 1, -1.0, 1, -1, 1]
Then:
?- sum_list(X, S).
S = 1.0
a positive result, so more positives than negatives in this case.
you could partition/4 the input list into the smaller vs larger values:
?- partition(>(0), [-2, 3.3, 12, -10.1, 14, -11, 123], Lesser, Greater).
Lesser = [-2, -10.1, -11],
Greater = [3.3, 12, 14, 123]
Then use length/2 and compare the result to see which one is longer.
(This might not be useful if any of the inputs are 0, they are not in your examples. I think this will use more memory to make a copy of the list.).
how to find out the solution to this problem in python/java or any other language:
Thanks in advance
Since a program isn't a proof and you would still need to prove it, here is some Python code:
def zig_zag(seq):
"""tests if binary sequence seq satsifies zig-zag pattern"""
for i in range(len(seq)-1):
if (i%2 == 0 and seq[i] > seq[i+1]) or (i%2 == 1 and seq[i] < seq[i+1]):
return False
return True
def count_zig_zags(n):
"""counts the number of binary zig-zag patterns of length n"""
count = 0
for i in range(2**n):
b = bin(i)[2:]
if zig_zag(b): count += 1
return count
For example:
>>> [count_zig_zags(n) for n in range(1,12)]
[2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]
A proof would be via strong induction.
I have tried to write a function for multiplying two matrices. Matrices are represented by lists inside lists like that [[1, 2], [3, 4]]. Although it gives result, it is not correct.
def Matrice_multiplicator(a, z):
if len(a[0])==len(z):
m=Matrice_create(len(a))
b=0
c=0
k=1-1
while b<len(a):
for i in range(len(a[b])):
while c<len(a[0]):
k+=a[b][c]*z[c][b]
print(k)
c+=1
m[b].append(k)
b+=1
return m
else:
return "Not multiplicable"
A matrix multiplication in standard Python could look like:
def matrix_multiplication(A, B):
a = len(A)
b = len(A[0])
c = len(B[0])
if b != len(B):
print (f"Wrong combination of dimensions: {a}x{b} and {len(B)}x{c}")
else:
return [[sum([A[i][k]*B[k][j] for k in range(b)])
for j in range(c)]
for i in range(a)]
A = [[1, 2, 3],
[4, 5, 6]]
B = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]]
print(matrix_multiplication(A, B))
Result:
[[38, 44, 50, 56],
[83, 98, 113, 128]]
How can i efficiently find the sum of all actual values of a totient function for given n.
for eg. tot(10) are 1,3,7,9 => 1+3+7+9 = 20.
I tried the brute force approach below
int sum = 0;
for(int i=1;i<n;i++)
{
if(gcd(i,n)==1)sum += i;
}
print(sum)
which is O(nxlog(n)).
where log(n) is for gcd computation at each step.
Constraints : 1<=n<=10^6.
If there exist any better solution?
If you print out the first values of the function, you get:
1, 1, 3, 4, 10, 6, 21, 16, 27, 20, 55, 24, 78, 42, 60, 64, 136, ...
Looking up the function in oeis, you find A023896: "Sum of totatives of n, i.e., sum of integers up to n and coprime to n". And there we get a formula:
n*phi(n)/2 except for n=1. Herephi is Euler's totient function, for which Euler himself indicated a fast calculation: n * Product_{distinct primes p dividing n} (1 - 1/p).
Putting everything together into some pure Python functions:
import math
def prime_factors(n):
if n == 1:
return []
if n % 2 == 0:
return [2] + prime_factors(n//2)
if n % 3 == 0:
return [3] + prime_factors(n//3)
if n % 5 == 0:
return [5] + prime_factors(n//5)
for i in range(6, int(math.sqrt(n)) + 1, 6):
if n % (i + 1) == 0:
return [i + 1] + prime_factors(n // (i + 1))
if n % (i + 5) == 0:
return [i + 5] + prime_factors(n // (i + 5))
return [n]
def gcd(a,b):
if b == 0:
return a
return gcd(b, a % b)
def totative_sum(n):
s = 0
for i in range(1, n+1):
if gcd(n, i) == 1:
s += i
return s
def phi(n):
prod = n
for i in set(prime_factors(n)): # convert to a set, because we don't want duplicates
# prod = prod * (1 - 1 / i)
prod = prod * (i - 1) // i # rewrite the formula to only work with integers
return int(prod)
def fast_totative_sum(n):
if n == 1:
return 1
return n * phi(n) // 2
print([totative_sum(n) for n in range(1, 31)])
print([fast_totative_sum(n) for n in range(1, 31)])
n = 12345678
print(fast_totative_sum(n))
print(totative_sum(n))
Output:
[1, 1, 3, 4, 10, 6, 21, 16, 27, 20, 55, 24, 78, 42, 60, 64, 136, 54, 171, 80, 126, 110, 253, 96, 250, 156, 243, 168, 406, 120]
24860442405888
Note that here the prime factorization only steps through possible factors of 6k+1 and 6k+5. This could be optimized even more, stepping modulo 30 where only 8 factors need to be tested and 22 can be skipped. (And so on, modulo 210=2*3*5*7 etc.).
If you need to calculate the prime factors for a lot of numbers, you could build a sieve of Eratosthenes and save the result in a list. That way you only need to step through real primes to find the prime factors.
If there is the F array in Julia as following
julia> F
5-element Array{Any,1}:
6
28
30
34
49
and I want to reach this
F
1-element Array{Any,1}:
Any[6, 28, 30, 34, 49]
this code is used
F[1]=vcat(F[1],F[2:end])
while true
k=2;
if length(F)==1
break;
end
filter!(x->x≠F[k],F)
end
It works. would you please help me? Is it possible to don't use while?
thanks very much