Best way to handle a ratings system [closed] - algorithm

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to implement a comparison rating system and I'm having difficulties finding the best way to handle this, especially from a database perspective.
Let's use food for an example.
The user is given pictures of two different foods and he chooses which one he likes better. He is then shown two more foods (one could be the same or they could both be different) and the user again selects. He continues to do this over and over and in doing so the application will TELL the user what his favorite food is, based solely on him saying which ones he likes more than others and comparing all these comparisons and displaying the results.
I've thought of just keeping track of the total likes/dislikes of each item, and I've also considered keeping track of every single choice in a massive database. I'm sure there's a way I've overlooked that is efficient for this kind of system.
Basically I'm looking not only for an efficient algorithm but also the best way to store this in a database.
Thanks for the help.

I'd just keep a database of triplets (user_id, preferred_id, dispreferred_id) corresponding to each choice.
EDIT: Had a bit of time to play with this. The following would be slow for millions of ratings, and gobble up memory, too, but might give you ideas. If you do go with this, you should probably run in asynchronously from crontab, rather by on-demand.
require 'set'
choices = [
[1, 4],
[1, 5],
[2, 3],
[2, 4],
[3, 1],
[4, 2],
[4, 3],
[5, 1],
[6, 7],
[8, 4],
]
dominates = Hash.new { |hash, key| hash[key] = Set.new }
choices.each do |p, d|
dominates[p].add(d)
end
prev_dominates = nil
while dominates != prev_dominates
prev_dominates = Hash.new
dominates.each { |big, smalls| prev_dominates[big] = smalls.clone }
prev_dominates.each do |big, smalls|
smalls.each do |small|
if prev_dominates.include?(small)
prev_dominates[small].each do |smaller|
if smaller != big and !prev_dominates[smaller].include?(big)
dominates[big] << smaller
end
end
end
end
end
end
top = dominates.max_by { |big, smalls| smalls.size }[0]
puts dominates.inspect
puts "BEST: #{top}"
The top node is the one that ends up dominating the most other nodes. However, given that the graph can be cyclic, we cut the cycle if another node would have completed the cycle sooner.

Related

Why is using inject/reduce more efficient than using map.with_index when working with large collections (in Ruby)?

I was working on a Codewar problem and the method I came up with worked with small arrays, but didn't work for very large arrays.
The solution provided used the inject method, which I assume is more efficient than the combination of map and with_index I had.
However, I'm not sure I understand why the inject method is more efficient than looping. Could someone please shine some light on this?
The problem was the following:
Given an array, return an array where each element is the sum of the array's subparts.
Example: array = [0, 1, 3, 6, 10]
I'm summing every array element while iterating on the array (so the array gets smaller and smaller):
[0, 1, 3, 6, 10] => 20
[1, 3, 6, 10] => 20
[3, 6, 10] => 19
[6, 10] => 16
[10] => 10
[] => 0
Hence the method would return here: [20, 20, 19, 16, 10, 0]
My solution (which works for small arrays but is too inefficient for large arrays):
def parts_sums(ls)
(ls + [0]).map.with_index { |_, i| ls[i..-1].sum }
end
The provided solution:
def parts_sums(ls)
ls.reduce([ls.sum]) { |sums, x| sums << sums.last - x }
end
By browsing the Codewars comment section, I've understood that this performance difference is linked to the Big O notation. However, every resource I found on this topic is way beyond my mathematical and algorithm understanding.
I've also looked at the Ruby doc but I don't understand C enough to be able to read the implementation of those methods.
Could someone please explain in quite simple terms why inject/reduce is more efficient than map.with_index in this situation?
Let’s start with reduce version.
ls.reduce([ls.sum]) { |sums, x| sums << sums.last - x }
It sums an array once (on step zero,) and then it subtracts two integers on each subsequent iteration.
Your solution sums the tail of the array on each step. Summing requires the whole array traversal, that’s why it is quite inefficient on large arrays.

WHICH algorithm would be best for word-search game similar with BOGGLE [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
Some of you may be familiar with the game called "BOGGLE".
Basically the game will display jumbled letters like this:
asdf
wcrq
nwoa
erdf
Then you need to look for all the possible answer in the board.
However I'm trying to develop a MOBILE GAME.
So here is what I'm planning:
I will ask the player to look for a SINGLE word in the given jumbled letters.
Example: look for the word CROWN in these letters:
asdf
wcrq
nwoa
erdf
Then I need to "trace" the answer CROWN out of this jumbled letters
But I don't know how I should implement that.
My problems are:
How will the letters jumbled by itself and then at the same time the game can maintain the right answer?
Every time the player traces the right answer, the next "look for the word" will display, then a new set of jumbled letters must be present
If the player trace a right answer, the next "look for the word" SHOULD appear IMMEDIATELY thus TIME must be observed.
The system must detect weather the player trace the right answer or not.
NOTE:
The player can trace to any direction he wants as long he won't jump to a letter to get the "look for the word."
Can you suggest algorithm and method or data structure to implement this?
I'm looking for a solution using HTML5, JavaScript and CSS.
Sample image:
Well, I would do iterative deepening with branch cutoff. For example:
1 2 3 4
5 6 7 8
9 0 A B
C D E F
There are 16 depth 1 nodes [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, A, B, C, D, E, F] and from any of them you can visit neighbor. For example If you choose 1:
* 2 3 4
5 6 7 8
9 0 A B
C D E F
List of depth 2 nodes would be [[1, 2], [1, 6], [1, 5]], then you check if your dictionary contains a word starting with any of them. If they do not then you can cut the branch! This is important, because otherwise there will be too much work to do. Lets assume [1, 2] did not exist and you picked [1, 6] :
* 2 3 4
5 * 7 8
9 0 A B
C D E F
List of depth 2 nodes would be [[1, 6, 2], [1, 6, 3], [1, 6, 7], [1, 6, A], [1, 6, 0], [1, 6, 9], [1, 6, 5]]. Like before you continue until you get to a node where there is no next move. Lets assume it is [1, 6, 2, 5]. Now you have longest word 4 letters long. After that you check if you get a longer word.
Depending on version you are playing you might want to adjust what result you take. For example in some versions you do not get extra points if you get a word longer then 8 letters - ex: if you find first 8 letter word you do not need to look further.
I hope this will get you started.

Fastest way to split ruby array following a structure [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I'm looking for the fastest way to split an array into sub-arrays with different size. The size of every array is driven by a configuration file.
Example:
c = [1,2,3,4,5,6,7,8]
My configuration file:
block
contents: 3
type: ...
scope ...
block
contents: 1
type: ...
scope ...
block
contents: 2
type: ...
scope ...
block
contents: 2
type: ...
scope ...
c.size is equal to the sum of the content number of every block.
I must split my array into 'n' arrays where n is the number of blocks I define in my config file and the size of every array is the number of contents defined in that block.
The result with the given array and config file is:
[1,2,3]
[4]
[5,6]
[7.8]
Any idea with good performance result?
A slight variant of Matt's answer:
If you read the values from the file into:
a = [3,1,2,2]
you can then do this:
a.each_with_object([]) {|e,b| b << c.shift(e)}
#=> [[1, 2, 3], [4], [5, 6], [7, 8]]
c = [1,2,3,4,5,6,7,8]
d = [3,1,2,2]
d.map { |n| c.shift n } # => [[1, 2, 3], [4], [5, 6], [7, 8]]
This destroys the original c.

Merging 2 Arrays based on one column [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions must demonstrate a minimal understanding of the problem being solved. Tell us what you've tried to do, why it didn't work, and how it should work. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have two arrays:
a = [[1234,1],[2134,0],[4321,0],[2221,3]]
b = [[2134,1],[4321,3]]
I want to merge them based on the first elements of a for the following result:
c = [[1234,1],[2134,1],[4321,3],[2221,3]]
I want to replace 0's in a by the value in b if the first element match. The first element is unique in a and b.
How do I do this?
Thanks in advance,
The Hash#merge function lets you specify a block to define what to do with the values.
a = [[1234,1],[2134,0],[4321,0],[2221,3]]
b = [[2134,1],[4321,3]]
c = Hash[a].merge(Hash[b]) { |key, old, new| old+new }.to_a
# => [[1234, 1], [2134, 1], [4321, 3], [2221, 3]]
See the Hash#merge documentation.
In this case I did the merge through building the sum of the values. You might want to choose the largest value, or some other strategy which fits you.
Disclaimer: This approach does not work, if a (or b) contains Arrays having the same first value. Example [[1, 1], [1, 4], [2, 8]]. It is not specified in your question if that can happen.
Given
a = [[1234,1],[2134,0],[4321,0],[2221,3]]
and
b = [[2134,1],[4321,3]]
You could transform these arrays into hashes, perform the merge, then transform the result into an array again.
Hash[a].merge(Hash[b]).to_a
#=> [[1234, 1], [2134, 1], [4321, 3], [2221, 3]]
Here's one possibility:
a = [[1234,1],[2134,0],[4321,0],[2221,3]]
b = [[2134,1],[4321,3]]
a.zip(b).flatten(1).uniq(&:first)
# => [[1234, 1], [2134, 1], [4321, 3], [2221, 3]]
[*a, *b].group_by(&:first).map{|k, v| [k, v.map(&:last).inject(:+)]}
Just reverse the arrays and call unique:
(b + a).uniq(&:first)
This works because Array#+ is a non-mutating version of Array#concat. It'll create a new ordered array. Whichever array is first, will take precedence in the output. When uniq is called, it will enumerate over the array in order, allowing you to just get the first instance of the first column.
You can do this for n arrays:
[b,d,c,a].reduce(&:+).uniq(&:first)

Difference Between map and each [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Ruby - What is the difference between map, each and collect?
I have looked in Ruby-Doc also but i cant understand the difference between
map
each
iterators.It would be great if you could give an example and explain.
each simply iterates over the given enumerable, running the block for each value. It discards the return value of the block, and each simply returns the original object it was called on:
[1, 2, 3].each do |x|
x + 1
end # => [1, 2, 3]
This is simply a nicer, more universal way of doing a traditional iterating for loop, and each is much preferred over for loops in Ruby (in fact, I don't think I've ever used a for loop in Ruby).
map, however, iterates over each element, using the return value of the block to populate a new array at each respective index and return that new array:
[1, 2, 3].map do |x|
x + 1
end # => [2, 3, 4]
So it “maps” each element to a new one using the block given, hence the name “map”. Note that neither each nor map themselves modify the original collection. This is a concise, functional alternative to creating an array and pushing to it in an iterative loop.
each returns the original object. It's used to run an operation using each element of an array without collecting any of the results. For example, if you want to print a list of numbers, you might do something like this:
arr = [1, 2, 3, 4]
arr.each { |n| puts n }
Now, that puts method above actually returns nil. Some people don't know that, but it doesn't matter much anyway; there's no real reason to collect that value (if you wanted to convert arr to strings, you should be using arr.map(&:to_s) or arr.map { |n| n.to_s }.
map returns the results of the block you pass to it. It's a great way to run an operation on each element in an array and retrieve the results. If you wanted to multiple every element of an array by 2, this is the natural choice. As a bonus, you can modify the original object using map!. For example:
arr = [1, 2, 3, 4]
arr.map! { |n| n * 2}
# => [2, 4, 6, 8]

Resources