Conditional constraints in OR SAT google not working as expected - or-tools

I am new with google OR SAT in python and the documentation is not very clear. What I am trying to do is the following:
There's a list like this:
desk[1] = 3
desk[2] = 5
desk[3] = 4
desk[4] = 2
desk[5] = 1
and a variable called person_la_croix, with value = 4, let's say.
I would like to create a boolean list (t) out of that t[i] = 1, if desk[i] != person_la_croix and 0 otherwise. And then I would like to take the i from t[i] which t[i] == 1 and assign it to variable desk_la_croix
I tried this:
for i in s:
model.Add(desk[i] == person_la_croix).OnlyEnforceIf(t[i])
for i in s:
model.Add(desk_la_croix == i).OnlyEnforceIf(t[i])
It is not working...
Can someone help me out either with this code or suggesting a smarter way to do this?

Have you read
https://github.com/google/or-tools/blob/stable/ortools/sat/doc/channeling.md ?
I guess you miss the opposite of the OnlyEnforceIf as these are only implications, not equivalences.

Related

"Find the Parity Outlier Code Wars (Scala)"

I am doing some of CodeWars challenges recently and I've got a problem with this one.
"You are given an array (which will have a length of at least 3, but could be very large) containing integers. The array is either entirely comprised of odd integers or entirely comprised of even integers except for a single integer N. Write a method that takes the array as an argument and returns this "outlier" N."
I've looked at some solutions, that are already on our website, but I want to solve the problem using my own approach.
The main problem in my code, seems to be that it ignores negative numbers even though I've implemented Math.abs() method in scala.
If you have an idea how to get around it, that is more than welcome.
Thanks a lot
object Parity {
var even = 0
var odd = 0
var result = 0
def findOutlier(integers: List[Int]): Int = {
for (y <- 0 until integers.length) {
if (Math.abs(integers(y)) % 2 == 0)
even += 1
else
odd += 1
}
if (even == 1) {
for (y <- 0 until integers.length) {
if (Math.abs(integers(y)) % 2 == 0)
result = integers(y)
}
} else {
for (y <- 0 until integers.length) {
if (Math.abs(integers(y)) % 2 != 0)
result = integers(y)
}
}
result
}
Your code handles negative numbers just fine. The problem is that you rely on mutable sate, which leaks between runs of your code. Your code behaves as follows:
val l = List(1,3,5,6,7)
println(Parity.findOutlier(l)) //6
println(Parity.findOutlier(l)) //7
println(Parity.findOutlier(l)) //7
The first run is correct. However, when you run it the second time, even, odd, and result all have the values from your previous run still in them. If you define them inside of your findOutlier method instead of in the Parity object, then your code gives correct results.
Additionally, I highly recommend reading over the methods available to a Scala List. You should almost never need to loop through a List like that, and there are a number of much more concise solutions to the problem. Mutable var's are also a pretty big red flag in Scala code, as are excessive if statements.

Scala - conditionally sum elements in list

I am trying to solve a beginner problem with lists but can't find an example to help me get it work. I am given a list of positive and negative integers (AccountHistory) and I need to check if the negative integers in this list have ever exceeded -1000. I expected my code to work with a freshly introduced helper function like this:
def checkAccount(account: AccountHistory): Boolean = {
def helper(i: AccountHistory): Int = {
var total = 0
i.collect{case x if x < 0 => Math.abs(x) + total}
return total
}
if (helper(account) >1000) true else false
}
But it doesn't work. Please help me find my mistake or problem in wrong approach.
Edit: The pre-given tests include
assert(checkAccount(List(10,-5,20)))
assert(!checkAccount(List(-1000,-1)))
So if assert expects true then my approach is wrong to solve it like this.
By 'exceeded' I mean <-1000, for any or all elements in a list (like exceeding a credit amount in given period).
i.collect{case x if x < 0 => Math.abs(x) + total}
In the above code snippet, not assign back to total, maybe you need:
val total = i.filter(_ < 0).map(Math.abs).sum
I think this is what you're supposed to do:
def checkAccount(account: AccountHistory): Boolean =
account.forall(_ > -1000)

Increment number in Dictionary

I have a Dictionary [String:AnyObject] which contains some keys and values.
I want to increment a key to which value is of type Double.
I can do it this way:
let nr = dict["number"] as! Double
dict["number"] = nr + 10
But I dont like that way so Im wondering if there is another way
I tried this:
(dict["number"] as! Double) += 10
But that gives me an error:
Binary operator '+=' cannot be applied to operands of type '(Double)' and 'Double'
Why isn't this working?
Following is an alternative. If you want to avoid force unwrapping an optional:
dict["number"] = (dict["number"] ?? 0) + 10
You are close and in fact you can write to a dictionary using +=, the problem is your cast. For example we can do:
var dict = ["number" : 2]
dict["number"]! += 10
and now dict["number"] returns 12. Now this is creating a new value (12) and replacing it into the dictionary, it is just a clean way of looking at it.
The problem with your code is that the left side (dict["number"] as! Double) gives you a Double. So you have say (12), then the right side is a Double too (10). So your code ends up looking like (12) += 10 which you can clearly see as problematic, since this is equivalent to 12 = 12 + 10, yikes!
So that being said, you can use the my first solution if you are working with native Swift dictionaries, otherwise your solved solution above works too, just a bit longer.
Lastly, if you are really looking for a one liner that works with your exact situation you should be able to do something like:
dict["number"] = (dict["number"] as! Double) + 10
Another option:
dict["number", default: 0] += 10
The safe way of casting would be:
if let num = dict["number"] as? Double {
dict["number"] = num + 10
}

Range Construction Pattern

Given the following code
import std.datetime: Clock, SysTime, Duration;
SysTime[] times;
const n = 3;
foreach (i; 0..n) times ~= Clock.currTime;
is there a simpler, perhaps functional, higher order pattern with
which to achieve the same goal?
A bonus would to be, when possible, minimize copyings of the elements perhaps through some in-place construction pattern.
See also: http://forum.dlang.org/thread/yofbijaejfyftpcjdcvd#forum.dlang.org#post-yofbijaejfyftpcjdcvd:40forum.dlang.org
Update:
Ok here's my try so far:
enum arityMin0(alias fun) = __traits(compiles, fun());
auto apply(alias fun, N)(N n) if (isCallable!fun &&
arityMin0!fun &&
!is(ReturnType!fun == void) &&
isIntegral!N)
{
import std.range: iota, map;
return n.iota.map!(n => fun);
}
called as, for instance,
import std.datetime: Clock;
auto times = 3.apply!(Clock.currTime).array;
One detail left. The restriction
arity!fun == 0
evaluate to false in
auto times = 3.apply!(Clock.currTime).array;
because arity is actually either 0 and 1 here.
So arity!fun evaluates to 1 in this case because Clock.currTime takes a defaulted argument.
Maybe we need arityMin and arityMax in std.traits aswell.
In that case should I use __traits(compiles to implement arityMin?
Evaluating currTime thrice:
auto times = 3.iota.map!(n => Clock.currTime).array();
Evaluating currTime once:
auto times = Clock.currTime.repeat(3).array();

Calculations with comprehensions

Let's say I have the following:
scoringObject =
a : -1
b : 0
c : 1
d : 2
resultsArray = ['a','c','b','b','c','c','d']
Using Coffescript, how can I calculate aggregateScore (+4 in the example) ?
Since your example doesn't make much sense as is, I'm going to assume that what you have is:
resultsArray = ['a','c','b','b','c','c','d']
with the scoringObject from your post. Then you could calculate like this:
aggregateScore = 0
aggregateScore += scoringObject[k] for k in resultsArray
# => 4
Let me know if I assumed wrongly.
If you don't mind using features from ECMAScript 5, Array::reduce lets you express this kind of thing quite succinctly:
aggregateScore = resultsArray.reduce ((sum, x) -> sum + scoringObject[x]), 0
(I feel that the parameter order of reduce is quite unfortunate; the initial value should be the first one, and the reducing function the last one)
Underscore.js provides a cross-browser reduce implementation :)