I'm getting this error when trying to sum a list I'm getting back from a comprehension:
range = 1..999
multiple_of_3_or_5? = fn(n) -> (rem(n, 3) == 0 || rem(n, 5) == 0) end
IO.inspect for n <- range, multiple_of_3_or_5?.(n),
do: Enum.reduce n, 0, fn(x) -> x end
#=> ** (FunctionClauseError) no function clause matching in Enum.reduce/3
Why am I getting this error?
The function in the third parameter of Enum.reduce needs to have two parameters, the element from the enumerable and an accumulator. You currently only have one parameter, x.
The first and third param are wrong. You can try this
range = 1..999
multiple_of_3_or_5? = fn(n) -> (rem(n, 3) == 0 || rem(n, 5) == 0) end
for n <- range, multiple_of_3_or_5?.(n) do n end |> Enum.reduce(0,
fn(x, acc) -> x + acc end)
or
range = 1..999
multiple_of_3_or_5? = fn(n) -> (rem(n, 3) == 0 || rem(n, 5) == 0) end
Enum.reduce_while(range, 0, fn i, acc ->
if multiple_of_3_or_5?.(i), do: {:cont, acc + i}, else: {:cont, acc}
end)
Related
For example, if I have the expression (A > 5) && (A == 6),
that expression can be simplified to just (A == 6), and still have the same behavior for A ∈ ℤ.
I also need it to work with multiple variables, so for instance ((B > 2) && (C == 2)) || ((B > 2) && (C < 2)) should simplify to (B > 2) && (C < 3).
I won't need to compare two unknowns, only unknowns and numbers, and I only need it to work with the operators <, >, and == for numbers, and && and || for expressions (&& being AND and || being OR, of course). All unknowns are integers.
Is there any algorithm that takes such an expression and returns an expression with equal behavior and a minimal amount of operators?
(in my specific case, || operators are preferred over &&)
Here's a slow dynamic programming algorithm along the lines that you were thinking of.
from collections import defaultdict, namedtuple
from heapq import heappop, heappush
from itertools import product
from math import inf
# Constructors for Boolean expressions. False and True are also accepted.
Lt = namedtuple("Lt", ["lhs", "rhs"])
Eq = namedtuple("Eq", ["lhs", "rhs"])
Gt = namedtuple("Gt", ["lhs", "rhs"])
And = namedtuple("And", ["lhs", "rhs"])
Or = namedtuple("Or", ["lhs", "rhs"])
# Variable names. Arbitrary strings are accepted.
A = "A"
B = "B"
C = "C"
# Example formulas.
first_example = And(Gt(A, 5), Eq(A, 6))
second_example = Or(And(Gt(B, 2), Eq(C, 2)), And(Gt(B, 2), Lt(C, 2)))
third_example = Or(And(Gt(A, 1), Gt(B, 1)), And(Gt(A, 0), Gt(B, 2)))
fourth_example = Or(Lt(A, 6), Gt(A, 5))
fifth_example = Or(And(Eq(A, 2), Gt(C, 2)), And(Eq(B, 2), Lt(C, 2)))
# Returns a map from each variable to the set of values such that the formula
# might evaluate differently for variable = value-1 versus variable = value.
def get_critical_value_sets(formula, result=None):
if result is None:
result = defaultdict(set)
if isinstance(formula, bool):
pass
elif isinstance(formula, Lt):
result[formula.lhs].add(formula.rhs)
elif isinstance(formula, Eq):
result[formula.lhs].add(formula.rhs)
result[formula.lhs].add(formula.rhs + 1)
elif isinstance(formula, Gt):
result[formula.lhs].add(formula.rhs + 1)
elif isinstance(formula, (And, Or)):
get_critical_value_sets(formula.lhs, result)
get_critical_value_sets(formula.rhs, result)
else:
assert False, str(formula)
return result
# Returns a list of inputs sufficient to compare Boolean combinations of the
# primitives returned by enumerate_useful_primitives.
def enumerate_truth_table_inputs(critical_value_sets):
variables, value_sets = zip(*critical_value_sets.items())
return [
dict(zip(variables, values))
for values in product(*({-inf} | value_set for value_set in value_sets))
]
# Returns both constants and all single comparisons whose critical value set is
# a subset of the given ones.
def enumerate_useful_primitives(critical_value_sets):
yield False
yield True
for variable, value_set in critical_value_sets.items():
for value in value_set:
yield Lt(variable, value)
if value + 1 in value_set:
yield Eq(variable, value)
yield Gt(variable, value - 1)
# Evaluates the formula recursively on the given input.
def evaluate(formula, input):
if isinstance(formula, bool):
return formula
elif isinstance(formula, Lt):
return input[formula.lhs] < formula.rhs
elif isinstance(formula, Eq):
return input[formula.lhs] == formula.rhs
elif isinstance(formula, Gt):
return input[formula.lhs] > formula.rhs
elif isinstance(formula, And):
return evaluate(formula.lhs, input) and evaluate(formula.rhs, input)
elif isinstance(formula, Or):
return evaluate(formula.lhs, input) or evaluate(formula.rhs, input)
else:
assert False, str(formula)
# Evaluates the formula on the many inputs, packing the values into an integer.
def get_truth_table(formula, inputs):
truth_table = 0
for input in inputs:
truth_table = (truth_table << 1) + evaluate(formula, input)
return truth_table
# Returns (the number of operations in the formula, the number of Ands).
def get_complexity(formula):
if isinstance(formula, bool):
return (0, 0)
elif isinstance(formula, (Lt, Eq, Gt)):
return (1, 0)
elif isinstance(formula, And):
ops_lhs, ands_lhs = get_complexity(formula.lhs)
ops_rhs, ands_rhs = get_complexity(formula.rhs)
return (ops_lhs + 1 + ops_rhs, ands_lhs + 1 + ands_rhs)
elif isinstance(formula, Or):
ops_lhs, ands_lhs = get_complexity(formula.lhs)
ops_rhs, ands_rhs = get_complexity(formula.rhs)
return (ops_lhs + 1 + ops_rhs, ands_lhs + ands_rhs)
else:
assert False, str(formula)
# Formula compared by complexity.
class HeapItem:
__slots__ = ["_complexity", "formula"]
def __init__(self, formula):
self._complexity = get_complexity(formula)
self.formula = formula
def __lt__(self, other):
return self._complexity < other._complexity
def __le__(self, other):
return self._complexity <= other._complexity
def __eq__(self, other):
return self._complexity == other._complexity
def __ne__(self, other):
return self._complexity != other._complexity
def __ge__(self, other):
return self._complexity >= other._complexity
def __gt__(self, other):
return self._complexity > other._complexity
# Like heapq.merge except we can add iterables dynamically.
class Merge:
__slots__ = ["_heap", "_iterable_count"]
def __init__(self):
self._heap = []
self._iterable_count = 0
def update(self, iterable):
iterable = iter(iterable)
try:
value = next(iterable)
except StopIteration:
return
heappush(self._heap, (value, self._iterable_count, iterable))
self._iterable_count += 1
def __iter__(self):
return self
def __next__(self):
if not self._heap:
raise StopIteration
value, index, iterable = heappop(self._heap)
try:
next_value = next(iterable)
except StopIteration:
return value
heappush(self._heap, (next_value, index, iterable))
return value
class Combinations:
__slots__ = ["_op", "_formula", "_best_formulas", "_i", "_n"]
def __init__(self, op, formula, best_formulas):
self._op = op
self._formula = formula
self._best_formulas = best_formulas
self._i = 0
self._n = len(best_formulas)
def __iter__(self):
return self
def __next__(self):
if self._i >= self._n:
raise StopIteration
formula = self._op(self._formula, self._best_formulas[self._i])
self._i += 1
return HeapItem(formula)
# Returns the simplest equivalent formula, breaking ties in favor of fewer Ands.
def simplify(target_formula):
critical_value_sets = get_critical_value_sets(target_formula)
inputs = enumerate_truth_table_inputs(critical_value_sets)
target_truth_table = get_truth_table(target_formula, inputs)
best = {}
merge = Merge()
for formula in enumerate_useful_primitives(critical_value_sets):
merge.update([HeapItem(formula)])
best_formulas = []
for item in merge:
if target_truth_table in best:
return best[target_truth_table]
formula = item.formula
truth_table = get_truth_table(formula, inputs)
if truth_table in best:
continue
n = len(best_formulas)
for op in [And, Or]:
merge.update(Combinations(op, formula, best_formulas))
best[truth_table] = formula
best_formulas.append(formula)
print(simplify(first_example))
print(simplify(second_example))
print(simplify(third_example))
print(simplify(fourth_example))
print(simplify(fifth_example))
Output:
Eq(lhs='A', rhs=6)
And(lhs=Lt(lhs='C', rhs=3), rhs=Gt(lhs='B', rhs=2))
And(lhs=And(lhs=Gt(lhs='B', rhs=1), rhs=Gt(lhs='A', rhs=0)), rhs=Or(lhs=Gt(lhs='B', rhs=2), rhs=Gt(lhs='A', rhs=1)))
True
Or(lhs=And(lhs=Eq(lhs='B', rhs=2), rhs=Lt(lhs='C', rhs=2)), rhs=And(lhs=Gt(lhs='C', rhs=2), rhs=Eq(lhs='A', rhs=2)))
Maybe you can consider intervals for your variables, for example:
(A > 5) && (A == 6)
Given you have a variable A, set an initial interval for it: A: [-∞, ∞].
Each condition that you read, you can reduce your interval:
(A > 5) sets the interval for A: [6, ∞]
(A == 6) sets the interval for A: [6, 6]
For each update on the interval, check if the new condition is possible, for example:
(A > 5) sets the interval for A: [6, ∞]
(A == 5) out of the interval, impossible condition.
Just another example:
((B > 2) && (C == 2)) || ((B > 2) && (C < 2))
Initially: B: [-∞, ∞] and C: [-∞, ∞].
((B > 2) && (C == 2))
(B > 2) sets the interval for B: [3, ∞]
(C == 2) sets the interval for C: [2, 2]
The next condition is attached with ||, so you add intervals:
((B > 2) && (C < 2))
(B > 2) sets the interval for B: [3, ∞]
(C < 2) sets the interval for C: [2, 2] U [-∞, 1] = [-∞, 2]
I am trying to create a recursive multiplier in ruby.
#j = 0
def multiplier(x, y, z)
count = 0
if x > 0
if z > 0
#j += y
z -= 1
count += 1
multiplier(x, y, z)
else
x -= 1
z = count
p z
multiplier(x, y, z)
end
else
return #j
end
end
def main
puts "Calculation is: " + multiplier(3, 10, 4).to_s
end
main
X is how many times the multiplication happens
Y is the number we want to multiply
Z is the number we multiply by
The code should output 120 with the variables that are there
I am having issues getting Z to stay what I need it to be. Also, I'd prefer to do this without a global variable
So something like x*(y*z) but without the times symbol
The main issue with your code is count is a local variable, it is not saved between recursive calls. Also, if you want to avoid globals, pass the variable as an additional parameter in call to the function. In FP we call it accumulator:
def multiplier(x, y, z, j = 0)
if z > 0
multiplier(x, y, z - 1, j + y)
elsif z.zero? # done with z, jump to x × (y × z)
# z = -1 to explicitly mark we are done with z
multiplier(x, j, -1, 0)
elsif y.zero? # yay, we are all set, reducing is done!
j
else
# still doing x × result step
multiplier(x, y - 1, -1, j + x)
end
end
multiplier(3, 10, 4)
#⇒ 120
The above surely lacks necessary checks for input validity, but I bet you got the idea.
Building on the recursive answer above, here's a more generic function that can take an arbitrarily long list of positive integers and multiply them by recursive addition:
def multiplier(*integers, accum: 0)
if integers.size == 1
# We are finished!
integers[0]
elsif integers[-1].positive?
# "Multiply" the last two integers, by recursive addition
integers[-1] -= 1
multiplier(*integers, accum: accum + integers[-2])
else
# The above multiplication is complete; set the last integer to its result
integers[-2] = accum
multiplier(*integers[0..-2])
end
end
I would say the idiomatic way in ruby is using iterators instead of recursion/cycles
def multiplier(x, y, z)
x.times.map do
y.times.map do
z
end.reduce(:+)
end.reduce(:+)
end
or
def multiplier(x, y, z)
x.times.map do
y.times.map do
z
end
end.flatten.reduce(:+)
end
Or if the only operation is inc
def multiplier(x, y, z)
j = 0
x.times do
y.times do
z.times do
j += 1
end
end
end
j
end
the output is the same
multiplier(3, 10, 4)
# 120
For an arbitrary number of args we have to use recursion
def multiplier(*xs, res: 0)
return res if xs.empty?
xs[0].times do
res += 1 if xs.size == 1
res = multiplier(*xs.drop(1), res: res)
end
res
end
or
def multiplier(*xs, res: 0)
head, *tail = xs
head.to_i.times do
res += 1 if tail.empty?
res = multiplier(*tail, res: res)
end
res
end
I'd start by writing a method to multiply two numbers recursively:
def multiply_2(a, b)
return 0 if a.zero?
b + multiply_2(a - 1, b)
end
multiply_2(3, 4)
#=> 12
and build upon that method to multiply three numbers:
def multiply_3(a, b, c)
multiply_2(multiply_2(a, b), c)
end
multiply_3(3, 4, 10)
#=> 3
and eventually extend that to handle n numbers:
def multiply_n(a, b, *more)
result = multiply_2(a, b)
return result if more.empty?
multiply_n(result, *more)
end
multiply_n(3, 4, 10, 2)
#=> 240
Note that you might run into a SystemStackError for large numbers. This can be avoided by making multiply_2 tail-recursive (leaving that as an exercise, it's not hard) and enabling Ruby's :tailcall_optimization.
It could be written thusly.
def multiplier(*args)
prod = recurse(*args.map(&:abs))
args.count { |n| n < 0 }.even? ? prod : -prod
end
def recurse(first, *rest)
first.zero? || rest.empty? ? first : ([recurse(*rest)]*first).sum
end
multiplier(3, 10, 4) #=> 120
multiplier(3, 10, 4, 2, 3) #=> 720
multiplier(3, -10, 4) #=> -120
multiplier(3, -10, -4) #=> 120
multiplier(3, 0, 4) #=> 0
multiplier(3, 0, -4) #=> 0
Suppose we wish to compute multiplier(3, -4). recurse(3, 4) is called, where
first = 3
rest = [4]
first.zero? #=> false
rest.empty? #=> false
so we compute
([recurse(4)]*3).sum
In recurse(4),
first = 4
rest = []
As rest.empty #=> true, recurse returns first #=> 4, so
([recurse(4)]*3).sum]
#=> ([4]*3).sum => [4,4,4].sum => 12
is returned to multiplier. As [3, -4] contains an odd number of negative values, multiplier returns -12.
def mergeSort(xs: List[Int]): List[Int] = {
val n = xs.length / 2
if (n == 0) xs
else {
def merge(xs: List[Int], ys: List[Int]): List[Int] =
(xs, ys) match {
case(Nil, ys) => ys
case(xs, Nil) => xs
case(x :: xs1, y :: ys1) =>
if (x < y) {
x :: merge(xs1, ys)
}
else {
y :: merge(xs, ys1)
}
}
val (left, right) = xs splitAt(n)
merge(mergeSort(left), mergeSort(right))
}
}
Inversion Count for an array indicates – how far (or close) the array is from being sorted. If array is already sorted then inversion count is 0. If array is sorted in reverse order that inversion count is the maximum.
Formally speaking, two elements a[i] and a[j] form an inversion if a[i] > a[j] and i < j
Example:
The sequence 2, 4, 1, 3, 5 has three inversions (2, 1), (4, 1), (4, 3).
So if this list(2, 4, 1, 3, 5)is passed to the function, the inversion count should be 3.
How do I add a variable to get the number?
May be something like will help
def mergeSort(xs: List[Int], cnt: Int): (List[Int], Int) = {
val n = xs.length / 2
if (n == 0) (xs, cnt)
else {
def merge(xs: List[Int], ys: List[Int], cnt: Int): (List[Int], Int) =
(xs, ys) match {
case(Nil, ys) => (ys, cnt)
case(xs, Nil) => (xs, cnt)
case(x :: xs1, y :: ys1) =>
if (x <= y) {
val t = merge(xs1, ys, cnt)
(x :: t._1, t._2)
}
else {
val t = merge(xs, ys1, cnt + xs.size)
(y :: t._1, t._2)
}
}
val (left, right) = xs splitAt(n)
val leftMergeSort = mergeSort(left, cnt)
val rightMergeSort = mergeSort(right, cnt)
merge(leftMergeSort._1, rightMergeSort._1, leftMergeSort._2 + rightMergeSort._2)
}
}
I am passing a tuple along all the function calls that's it.
I increment the value of the cnt when we find that first element of one list is less than the first element of second list. In this scenario we add list.length to the cnt. Look at the code, to get a more clear view.
Hope this helps!
I am trying to test a binary search algorithm. The logic seems right, however, I'm running into some issues.
There are two different methods, case and if. If one method fails, the other is right.
1.
arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
def search(arr, value)
if arr.nil?
return "value not in array"
end
l = 0
u = (arr.length - 1)
t = value
if l > u
puts "array is wrong!"
return
end
while l < u
m = (l + u) / 2
case m
when m < t
l = (m + 1)
when m == t
puts "hello world"
when m > t
u = (m - 1)
end
end
end
search(arr, 5)
2.
def search(arr, value)
if arr.nil?
return "value not in array"
end
l = 0
u = (arr.length - 1)
t = value
if l > u
puts "array is wrong!"
return
end
while l < u
m = (l + u) / 2
if m < t
l = (m + 1)
elsif m == t
puts "hello world"
break
elsif m > t
u = (m - 1)
end
end
end
I thought my code would work, but something is causing my while loop to go on infinitely. What am I doing to cause an infinite loop?
I am wondering about this line:
{ |i| (num % i) == 0}.length == 0
Can someone explain what happens using length on a block? I am trying to answer a rubeque problem about prime factors:
divisors = Array.new
for d in 2..(num)
divisors << d if (num % d) == 0
end
primes = divisors.select do |num|
(2..(num-1)).select { |i| (num % i) == 0}.length == 0
end
It's calling length on the result of (2..(num-1)).select { |i| (num % i) == 0} — which is an array — not on the block.