Comparing two NSMutableDictionaries - objective-c

Hello fellow Computer People!
I could do this myself, but was just wondering if there was a more efficient way that I haven't though of:
I have two NSMutableDictionaries. Let us use these as an example:
Dictionary 'Madrid'
Bob : 54
Thomas : 32
Frank : 20
Dictionary 'Barcelona'
Bob : 1100
Thomas : 32
Ed : 55
Frank : 20
What I want to get from comparing these two is:
The fact that the value for Bob is different between the two Dictionaries
That Frank has a value in Barcelona, but was not at all in Madrid.
This is for monitoring a sort of time series to see if any activity is happening from one iteration to the next.
Obviously this should be dealt with in Objective-C.
Any opinions on the most efficient way of doing this?
Thanks so much!

Probably the best way would involve a simple loop through one of the dictionaries, then check to see if you missed any keys in the other dictionary. Since dictionaries are involved it would only be O(N)

Objective-C supports isEqualToDictionary:
Usage:
if ([(NSDictionary *)mutableDictionary1 isEqualToDictionary:(NSDictionary *)mutableDictionary2]) {

Related

Pharo dictionary

I have an issue and this is the result when i call one method in my code.
t do:[:i |
dict := Dictionary newFrom:{t->items}.
].
t is an
OrderedCollection(#name #lastName #birthDate)
and items too. items an OrderedCollection('cs0yh1n1b2bm0wps16uvy7tfi' 'cs0yh1k1t3bgdszfupe407qdg' 21 April 1975)
a Dictionary [1 item] (an OrderedCollection(#name #lastName #birthDate)->an OrderedCollection('cs0yh1n1b2bm0wps16uvy7tfi' 'cs0yh1k1t3bgdszfupe407qdg' 21 April 1975).
I would like to obtain a gender dictionary
a Dictionary (#name->'cs0yh1n1b2bm0wps16uvy7tfi' #lastNamename->'cs0yh1k1t3bgdszfupe407qdg' #birthDay->21 April 1975)
how can i do this please ?
You are creating a new Dictionary each time through the loop. You need to create a new (empty) Dictionary before the loop and add each element using #'at:put:'. If you want to map index 1 in t to index 1 in items, then you need to have a counter. Perhaps 1 to: t size do: [:i | ...].
You are asking a lot of questions about Smalltalk and we are delighted to have you learning it. Have you tried spending a few hours studying a book or taking a course? I recommend the Pharo Mooc, some Pharo books, or some Smalltalk books.

Understanding Google Code Jam 2013 - X Marks the Spot

I was trying to solve Google Code Jam problems and there is one of them that I don't understand. Here is the question (World Finals 2013 - problem C): https://code.google.com/codejam/contest/2437491/dashboard#s=p2&a=2
And here follows the problem analysis: https://code.google.com/codejam/contest/2437491/dashboard#s=a&a=2
I don't understand why we can use binary search. In order to use binary search the elements have to be sorted. In order words: for a given element e, we can't have any element less than e at its right side. But that is not the case in this problem. Let me give you an example:
Suppose we do what the analysis tells us to do: we start with a left bound angle of 90° and a right bound angle of 0°. Our first search will be at angle of 45°. Suppose we find that, for this angle, X < N. In this case, the analysis tells us to make our left bound 45°. At this point, we can have discarded a viable solution (at, let's say, 75°) and at the same time there can be no more solutions between 0° and 45°, leading us to say that there's no solution (wrongly).
I don't think Google's solution is wrong =P. But I can't figure out why we can use a binary search in this case. Anyone knows?
I don't understand why we can use binary search. In order to use
binary search the elements have to be sorted. In order words: for a
given element e, we can't have any element less than e at its right
side. But that is not the case in this problem.
A binary search works in this case because:
the values vary by at most 1
we only need to find one solution, not all of them
the first and last value straddle the desired value (X .. N .. 2N-X)
I don't quite follow your counter-example, but here's an example of a binary search on a sequence with the above constraints. Looking for 3:
1 2 1 1 2 3 2 3 4 5 4 4 3 3 4 5 4 4
[ ]
[ ]
[ ]
[ ]
*
I have read the problem and in the meantime thought about the solution. When I read the solution I have seen that they have mostly done the same as I would have, however, I did not thought about some minor optimizations they were using, as I was still digesting the task.
Solution:
Step1: They choose a median so that each of the line splits the set into half, therefore there will be two provinces having x mines, while the other two provinces will have N - x mines, respectively, because the two lines each split the set into half and
2 * x + 2 * (2 * N - x) = 2 * x + 4 * N - 2 * x = 4 * N.
If x = N, then we were lucky and accidentally found a solution.
Step2: They are taking advantage of the "fact" that no three lines are collinear. I believe they are wrong, as the task did not tell us this is the case and they have taken advantage of this "fact", because they assumed that the task is solvable, however, in the task they were clearly asking us to tell them if the task is impossible with the current input. I believe this part is smelly. However, the task is not necessarily solvable, not to mention the fact that there might be a solution even for the case when three mines are collinear.
Thus, somewhere in between X had to be exactly equal to N!
Not true either, as they have stated in the task that
You should output IMPOSSIBLE instead if there is no good placement of
borders.
Step 3: They are still using the "fact" described as un-true in the previous step.
So let us close the book and think ourselves. Their solution is not bad, but they assume something which is not necessarily true. I believe them that all their inputs contained mines corresponding to their assumption, but this is not necessarily the case, as the task did not clearly state this and I can easily create a solvable input having three collinear mines.
Their idea for median choice is correct, so we must follow this procedure, the problem gets more complicated if we do not do this step. Now, we could search for a solution by modifying the angle until we find a solution or reach the border of the period (this was my idea initially). However, we know which provinces have too much mines and which provinces do not have enough mines. Also, we know that the period is pi/2 or, in other terms 90 degrees, because if we move alpha by pi/2 into either positive (counter-clockwise) or negative (clockwise) direction, then we have the same problem, but each child gets a different province, which is irrelevant from our point of view, they will still be rivals, I guess, but this does not concern us.
Now, we try and see what happens if we rotate the lines by pi/4. We will see that some mines might have changed borders. We have either not reached a solution yet, or have gone too far and poor provinces became rich and rich provinces became poor. In either case we know in which half the solution should be, so we rotate back/forward by pi/8. Then, with the same logic, by pi/16, until we have found a solution or there is no solution.
Back to the question, we cannot arrive into the situation described by you, because if there was a valid solution at 75 degrees, then we would see that we have not rotated the lines enough by rotating only 45 degrees, because then based on the number of mines which have changed borders we would be able to determine the right angle-interval. Remember, that we have two rich provinces and two poor provinces. Each rich provinces have two poor bordering provinces and vice-versa. So, the poor provinces should gain mines and the rich provinces should lose mines. If, when rotating by 45 degrees we see that the poor provinces did not get enough mines, then we will choose to rotate more until we see they have gained enough mines. If they have gained too many mines, then we change direction.

Objective-C algorithm to find largest common subsets of arrays?

I'm currently in need of an efficient solution to finding the largest common subsets of multiple arrays.
For example:
Let's say a user, Chris, wants to find other users with common interests (from most common to least common); we'd have to compare his array of interests with other users' arrays and find the largest common subset to the smallest common subset.
Chris {bowling, gaming, skating, running}
And other users in database.
Brad {bowling, jumping, walking, sitting}
John {bowling, gaming, skating, eating}
Sarah {bowling, gaming, drawing, coding}
So Chris has the most common interests, respectively, with John, then Sarah, then Brad.
How would I, in Objective-C, be able to do this? Any pointers would be great.
You are looking for an algorithm to find the cardinality of a set intersection.
Depending on your set representation, you could choose different ways of doing it. The most performant representation for this would be using bits in an integer, but if the number of possible interests exceeds 64 this may not be easy to implement.
A straightforward way of implementing it would be with NSMutableSet, like this:
// Prepare the individual lists
NSArray *chris = #[#"bowling", #"gaming", #"skating", #"running"];
NSArray *brad = #[#"bowling", #"jumping", #"walking", #"sitting"];
// Obtain the intersection
NSMutableSet *common = [NSMutableSet setWitArray:chris];
[common intersectSet:[NSSet setWithArray:brad]];
NSLog(#"Common interest count: %i", common.count);

Prolog game programming board evaluation

I have created a game, (4 in a row), in prolog. My heuristic function requires me to know how many Player's and Opponent's chips are in each possible 4-row combination on the board. The method I am using is as follows (in psuedocodish):
I have 1 list of all possible fours of the board (ComboList) =of the form==> [[A,B,C,D]|Rest].
I have 1 list of all the moves of the 1st player (List1) =of the form==> [[1],[7],[14]]
And 1 for opponent's moves (List2).
Step 1: obtain the first combo from ComboList, 2:
Check all of List1 to see how many are in this combo, 3:
Check all of List2 to see how many are in this combo,
Move onto the next combo from ComboList and start over...
This PROCESS takes waay too much runtime for what is required.
Please can someone suggest something better and more efficient! Much thanks in advance!
The following code uses member/3, which has also to become
known as nth1/3. See here:
http://storage.developerzen.com/fourrow.pro.txt
The predicate is nowadays found in library(lists) and has
possibly native support or a fast implementation:
http://www.swi-prolog.org/pldoc/man?predicate=nth1/3
But I guess asserting some facts and relying on argument
indexing might get you an even better result. See for
example here:
http://www.mxro.de/applications/four-in-a-row
Hope this helps.
Bye

Datefield changes to 2069 or 1970

I have a datefield in flex with editable="true".
When I type: 20-1-69 and I go to another field, it changes into 20-01-2069. but I don't want it to change into 2069. Is it possible to turn off this automatically change thing?
Thanks,
JSMB
In the past, when bytes where expensive, smart programmers used two digits to store the date. So a 60 was interpreted as an 1960 and all was wel.
Until the dreaded year 2000 was near, people started to panic, because computers would certainly stop to work and we would all die, or at least been cut from the Internet which is possibly worse.
So smart programmers were called to solve the problem.
Real smart programmers extended the number of digits to 4. But programmers that were self proclaimed smart, used the sliding window. 70 to 99 where interpreted as 1970-1999 and 0 to 69 was ineterpreted as 2000 to 2069. This of course solved the Y2K problem. But as you have found out, we have a 2070 problem.
The fun part is that, using this scheme, old guys like me are born in the future. Which makes us feel young again. So they probably did this on purpose.
You need to decide where you want the two-digit date to cut off between 1900 and 2000, and then perform some magic on the input.
Example: Cutoff is the year 1940
(pseudocode)
If twoDigitYear > 40
fourDigitYear = "19" + twoDigitYear
Else
fourDigitYear = "20" + twoDigitYear
This will give you years from 1941 to 2040.
Use a DateValidator to enforce a 4 digit year? If you're going to be entering in old dates, this is pretty much a requirement no matter what SDK you have. Even if you work out some way to make this work, some user will come along and get confused.