Prolog - Recursion exiting giving the wrong value - recursion

So I made this code to find the intersection between two lists.
intersect([], _, C).
intersect([A1|AS], B, C) :-
member(A1, B), length(C, L), L =:= 0, intersect(AS, B, [A1]);
member(A1, B), length(C, L), L =\= 0, append(C, [A1], D), intersect(AS, B, D);
intersect(AS, B, C).
And it indeed finds the intersections when the list A is empty, however it the value for C will be an empty list.
Using trace on this command "intersect([1,2,3,4,5,6,7,8],[4,5,6], C)." I get this:
> Call: (16) intersect([], [4, 5, 6], [4, 5, 6]) ? creep Exit: (16)
> intersect([], [4, 5, 6], [4, 5, 6]) ? creep Exit: (15)
> intersect([8], [4, 5, 6], [4, 5, 6]) ? creep Exit: (14)
> intersect([7, 8], [4, 5, 6], [4, 5, 6]) ? creep Exit: (13)
> intersect([6, 7, 8], [4, 5, 6], [4, 5]) ? creep Exit: (12)
> intersect([5, 6, 7, 8], [4, 5, 6], [4]) ? creep Exit: (11)
> intersect([4, 5, 6, 7, 8], [4, 5, 6], []) ? creep Exit: (10)
> intersect([3, 4, 5, 6, 7, 8], [4, 5, 6], []) ? creep Exit: (9)
> intersect([2, 3, 4, 5, 6, 7, 8], [4, 5, 6], []) ? creep Exit: (8)
> intersect([1, 2, 3, 4, 5, 6, 7, 8], [4, 5, 6], []) ? creep
Note how at the Call the value of C has been found and it is correct. However as it exits the recursion it just reverts back to its original value, how can I fix this? (If I add write(C) at the base case it will print the right value.)

Here is a specialization of your program by adding false goals:
intersect([], _, C).
intersect([A1|AS], B, C) :-
( false, member(A1, B), length(C, L), L =:= 0,
intersect(AS, B, [A1])
; false, member(A1, B), length(C, L), L =\= 0,
append(C, [A1], D),
intersect(AS, B, D)
; intersect(AS, B, C)
).
By adding false certain solutions have been removed. However, what remains is the last alternative, which always applies. You need to address this.
And write in stead of length(C, L), L =:= 0 rather C = [] and instead of length(C, L), L =\= 0 rather C = [_|_].

Related

How to combine two vectors of references without consuming an iterator?

I want to combine two reference vectors and convert them into a vector of values without consuming an iterator.
Situation:
Generate vectors by iterating over specific combinations. (2 elements from one vector, 2 elements from another vector)
Code:
use core::iter::Iterator;
use itertools::Itertools;
fn main() {
let vec_a: Vec<u8> = vec![1, 2, 3];
let vec_b: Vec<u8> = vec![4, 5, 6];
// a: Vec<&u8>
for a in vec_a.iter().combinations(2) {
// b: Vec<&u8>
for b in vec_b.iter().combinations(2) {
// c: Vec<u8> <- a + b
let c: Vec<u8> = a.clone().into_iter().chain(b).cloned().collect();
println!("a: {:?}, b: {:?}, c: {:?}", a, b, c);
}
}
}
Expected output:
a: [1, 2], b: [4, 5], c: [1, 2, 4, 5]
a: [1, 2], b: [4, 6], c: [1, 2, 4, 6]
a: [1, 2], b: [5, 6], c: [1, 2, 5, 6]
a: [1, 3], b: [4, 5], c: [1, 3, 4, 5]
a: [1, 3], b: [4, 6], c: [1, 3, 4, 6]
a: [1, 3], b: [5, 6], c: [1, 3, 5, 6]
a: [2, 3], b: [4, 5], c: [2, 3, 4, 5]
a: [2, 3], b: [4, 6], c: [2, 3, 4, 6]
a: [2, 3], b: [5, 6], c: [2, 3, 5, 6]
P.S.
I read the following link before posting my question. However, the answer to this question consumes Vec and its iterator, so it did not work in this situation.
Best way to concatenate vectors in Rust
Thanks to #ChayimFriedman.
There are some ways to do this.
Without consumption
// a: Vec<&u8>
// b: Vec<&u8>
let c: Vec<u8> = a.iter().chain(&b).copied().copied().collect();
println!("a: {:?}", a);
println!("b: {:?}", b);
With consumption
// a: Vec<&u8>
// b: Vec<&u8>
let c: Vec<u8> = a.into_iter().chain(b).copied().collect();
// println!("a: {:?}", a); -> compile error
// println!("b: {:?}", b); -> compile error

Julia idiomatic way to split vector to subvectors based on condition

Let's say I have a vector a = [1, 0, 1, 2, 3, 4, 5, 0, 5, 6, 7, 8, 0, 9, 0] and I want to split it to smaller vectors based on a condition depending on value in that array. E.g. value being zero.
Thus I want to obtain vector of following vectors
[1, 0]
[1, 2, 3, 4, 5, 0]
[5, 6, 7, 8, 0]
[9, 0]
So far this was working for me as a naive solution, but it loses the type.
function split_by_λ(a::Vector, λ)
b = []
temp = []
for i in a
push!(temp, i)
if λ(i)
push!(b, temp)
temp = []
end
end
b
end
split_by_λ(a, isequal(0))
Then I tried to play with ranges, which feels a bit more idiomatic, and does not lose the type.
function split_by_λ(a::Vector, λ)
idx = findall(λ, a)
ranges = [(:)(i==1 ? 1 : idx[i-1]+1, idx[i]) for i in eachindex(idx)]
map(x->a[x], ranges)
end
split_by_λ(a, isequal(0))
but it still feels very cumbersome regarding it's a rather simple task.
Is there something I'm missing, some easier way?
Maybe someone has a shorter idea but here is mine:
julia> inds = vcat(0,findall(==(0),a),length(a))
julia> getindex.(Ref(a), (:).(inds[1:end-1].+1,inds[2:end]))
5-element Array{Array{Int64,1},1}:
[1, 0]
[1, 2, 3, 4, 5, 0]
[5, 6, 7, 8, 0]
[9, 0]
[]
Or if you want to avoid copying a
julia> view.(Ref(a), (:).(inds[1:end-1].+1,inds[2:end]))
5-element Array{SubArray{Int64,1,Array{Int64,1},Tuple{UnitRange{Int64}},true},1}:
[1, 0]
[1, 2, 3, 4, 5, 0]
[5, 6, 7, 8, 0]
[9, 0]
0-element view(::Array{Int64,1}, 16:15) with eltype Int64
Pretty much the same as Przemyslaw's answer, but maybe less cryptic dense:
function split_by(λ, a::Vector)
first, last = firstindex(a), lastindex(a)
splits = [first-1; findall(λ, a); last]
s1, s2 = #view(splits[1:end-1]), #view(splits[2:end])
return [view(a, i1+1:i2) for (i1, i2) in zip(s1, s2)]
end
Also, I changed the signature to the conventional one of "functions first", which allows you to use do-blocks. Additionally, this should work with offset indexing.
One could surely get rid of the intermediate allocations, but I think that gets ugly without yield:
function split_by(λ, a::Vector)
result = Vector{typeof(view(a, 1:0))}()
l = firstindex(a)
r = firstindex(a)
while r <= lastindex(a)
if λ(a[r])
push!(result, #view(a[l:r]))
l = r + 1
end
r += 1
end
push!(result, #view(a[l:end]))
return result
end

How to multiply two matrices?

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]]

Find all cycles of given length (networkx)

Given an undirected graph how do you go about finding all cycles of length n (using networkx if possible). So input would be the Graph and n and the function would return all cycles of that length.
You can use networkx.cycle_basis.
>>> G = networkx.Graph()
>>> networkx.add_cycle(G, [0, 1, 2, 3])
>>> networkx.add_cycle(G, [0, 3, 4, 5])
>>> print(networkx.cycle_basis(G))
[[3, 4, 5, 0], [1, 2, 3, 0]]
>>> print(networkx.cycle_basis(G, root = 2))
[[1, 2, 3, 0]]
Then, you can check the length of each list as you see fit.

Sum of integers with restrictrions

Getting right to the gist of the problem:
In how many ways can we add k positive integers to reach a sum of exactly n if each number is smaller or equal to given number m?
The problem is solvable with dynamic programming but I am stuck because I cannot find the optimal substructure or recursion for the solution.
Here's a simple function in Python 3 that should fit your description. I assume that 0 is not an acceptable value but it's a trivial change if it is.
def howMany(k, n, m):
def sub(pos, currentSum, path):
if currentSum == n and pos == k: # reached the sum, print result and increase counter by 1
print(path)
return 1
elif currentSum < n and pos < k: # still worth trying
count = 0
for i in range(1, m):
count += sub(pos + 1, currentSum + i, path+[i])
return count
else: # abort
return 0
return sub(0, 0, [])
print(howMany(3, 10, 6))
yields
[1, 4, 5]
[1, 5, 4]
[2, 3, 5]
[2, 4, 4]
[2, 5, 3]
[3, 2, 5]
[3, 3, 4]
[3, 4, 3]
[3, 5, 2]
[4, 1, 5]
[4, 2, 4]
[4, 3, 3]
[4, 4, 2]
[4, 5, 1]
[5, 1, 4]
[5, 2, 3]
[5, 3, 2]
[5, 4, 1]
18
It could be optimised but that would obfuscate the logic at this stage.

Resources