Pequeño juego de adivinanzas en Ruby -- algorithm campo con ruby campo con game camp codereview Relacionados El problema

Small guessing game in Ruby


5
vote

problema

Español

Estoy escribiendo un pequeño juego de adivinanzas. Estoy escribiendo un algoritmo de cálculo de puntos.

Escribí lo siguiente, y funciona. Pero siento que estoy trayendo sobre fondo procesal a Ruby, o no aprovechando el rubí correctamente.

¿Cómo se abordaría un experimentado programador de rubí en el problema? Puede probar el código en tryruby.com (Copiar y pegar el código en el intérprete del navegador).

  # g = guesses g = [{ id: 1, elmer­: 5, roger: 7, outcome: "Roger Win" },{ id: 2, elmer: 5, roger: 1, outcome: "Elmer Win" },{ id: 3, elmer: 4, roger: 8, outcome: "Roger Win" }] # r = actual results r = [{ id: 1, elmer: 3, roger: 9, outcome: "Roger Win" },{ id: 2, elmer: 7, roger: 9, outcome: "Roger Win" },{ id: 3, elmer: 4, roger: 8, outcome: "Roger Win" }] # points table p = []     # rules: correct outcome = 1 point, perfect match = 5 points.  # Loop over results. r.each do |result|    # Loop over guesses.   g.each do |guess|      # Make sure we compare corresponding ids.     # So, compare result 1 to guess 1, r2 to g2, etc....     if result[:id] == guess[:id]        # Init a hash to store score       score = {}        # Did they guess the correct outcome?       if result[:outcome] == guess[:outcome]          # Correct outcome guessed! Make a score hash, give'em a point.         score[:id]     = result[:id]  # game id         score[:points] = 1            # point          # Was it a perfect match?         if result[:elmer] == guess[:elmer] && result[:roger] == guess[:roger]            # Perfect match! Give them 4 points.           # They already got 1 point for guessing the correct outcome.           score[:points] += 4         end       end        # Add the score to the points table       p.push(score) unless score.empty?     end   end end   
Original en ingles

I'm writing a small guessing game. I'm writing a points calculation algorithm.

I wrote the following, and it works. But I feel like I'm bringing over procedural background into Ruby, or not leveraging Ruby properly.

How would an experienced Ruby programmer approach the problem? You can test the code on TryRuby.com (copy and paste code in the browser interpreter).

# g = guesses g = [{ id: 1, elmerxc2xad: 5, roger: 7, outcome: "Roger Win" },{ id: 2, elmer: 5, roger: 1, outcome: "Elmer Win" },{ id: 3, elmer: 4, roger: 8, outcome: "Roger Win" }] # r = actual results r = [{ id: 1, elmer: 3, roger: 9, outcome: "Roger Win" },{ id: 2, elmer: 7, roger: 9, outcome: "Roger Win" },{ id: 3, elmer: 4, roger: 8, outcome: "Roger Win" }] # points table p = []     # rules: correct outcome = 1 point, perfect match = 5 points.  # Loop over results. r.each do |result|    # Loop over guesses.   g.each do |guess|      # Make sure we compare corresponding ids.     # So, compare result 1 to guess 1, r2 to g2, etc....     if result[:id] == guess[:id]        # Init a hash to store score       score = {}        # Did they guess the correct outcome?       if result[:outcome] == guess[:outcome]          # Correct outcome guessed! Make a score hash, give'em a point.         score[:id]     = result[:id]  # game id         score[:points] = 1            # point          # Was it a perfect match?         if result[:elmer] == guess[:elmer] && result[:roger] == guess[:roger]            # Perfect match! Give them 4 points.           # They already got 1 point for guessing the correct outcome.           score[:points] += 4         end       end        # Add the score to the points table       p.push(score) unless score.empty?     end   end end 
        

Lista de respuestas

5
 
vote
vote
La mejor respuesta
 

Proponfo primero cómo mejorar su algoritmo sin cambiar las estructuras de datos.

Su algoritmo es cuadrático (dos bucles anidados sobre todas las entradas). Esto se puede evitar fácilmente porque no necesita hacer un bucle durante todo el 9988776665544330 para encontrar el elemento que necesita.

Si no lo están, ordena las matrices por la tecla id , usando sort_by :

  r.sort_by! { |e| e[:id] } g.sort_by! { |e| e[:id] }   

Luego, puede usar cada_with_index :

  r.each_with_index { |result, i|     guess = g[i]      # compute the score here }   

o, si la velocidad no es un problema (y esto no parece ser el caso), también puede ZIP Las matrices juntas r.zip(g) y itera en eso:

  r.zip(g).each { |result, guess|     # compute the score here }   

Si puede modificar la estructura de datos, propongo algunas alternativas.

A menudo, cuando tiene un conjunto de objetos con una ID, usa un hash.

  # g = guesses g = {1 => { elmer­: 5, roger: 7, outcome: "Roger Win" }, 2 => {elmer: 5, roger: 1, outcome: "Elmer Win" }, 3 => { elmer: 4, roger: 8, outcome: "Roger Win" }} # r = actual results r = {1 => { elmer: 3, roger: 9, outcome: "Roger Win" }, 2 => {elmer: 7, roger: 9, outcome: "Roger Win" }, 3 => { elmer: 4, roger: 8, outcome: "Roger Win" }} # points table p = {}  # Loop over results. r.each { |id, result|   guess = g[id]    # Init a hash to store score   score = {}    # compute the score here   # ...    p[id] = score unless score.empty? }   

Si la identificación es un entero incremental simple y agrega las entradas en r y 9988776655544338 En el mismo orden, puede evitar la identificación en absoluto y usar la matriz Índices en lugar:

  # g = guesses g = [{ elmer­: 5, roger: 7, outcome: "Roger Win" }, {elmer: 5, roger: 1, outcome: "Elmer Win" }, { elmer: 4, roger: 8, outcome: "Roger Win" }] # r = actual results r = [{ elmer: 3, roger: 9, outcome: "Roger Win" }, {elmer: 7, roger: 9, outcome: "Roger Win" }, { elmer: 4, roger: 8, outcome: "Roger Win" }] # points table p = {}  # Loop over results. r.each_with_index { |result, id|   guess = g[id]    # Init a hash to store score   score = {}    # compute the score here   # ...    p[id] = score unless score.empty? }   

Puede crear una clase para representar cada entrada de la matriz (llamemos a cada entrada una entrada una entrada) y luego implemente el algoritmo de puntuación como método:

  id0  

Ejemplo de uso:

  id1  

Si el argumento de la cadena solo dice quién es el ganador según los números, puede calcularlo:

  id2  

Ejemplo de uso:

  id3  
 

I first propose how to improve your algorithm without changing the data structures.

Your algorithm is quadratic (two nested loops over all the entries). This can be easily avoided because you don't need to loop over all the g array to find the item you need.

If they are not, sort the arrays by the id key, using sort_by:

r.sort_by! { |e| e[:id] } g.sort_by! { |e| e[:id] } 

Then you can use each_with_index:

r.each_with_index { |result, i|     guess = g[i]      # compute the score here } 

or, if speed is not an issue (and this does not seem to be the case), you can also zip the arrays together r.zip(g) and iterate on that:

r.zip(g).each { |result, guess|     # compute the score here } 

If you can modify the data structure I propose some alternatives.

Often when you have a set of objects with an id you use a hash.

# g = guesses g = {1 => { elmerxc2xad: 5, roger: 7, outcome: "Roger Win" }, 2 => {elmer: 5, roger: 1, outcome: "Elmer Win" }, 3 => { elmer: 4, roger: 8, outcome: "Roger Win" }} # r = actual results r = {1 => { elmer: 3, roger: 9, outcome: "Roger Win" }, 2 => {elmer: 7, roger: 9, outcome: "Roger Win" }, 3 => { elmer: 4, roger: 8, outcome: "Roger Win" }} # points table p = {}  # Loop over results. r.each { |id, result|   guess = g[id]    # Init a hash to store score   score = {}    # compute the score here   # ...    p[id] = score unless score.empty? } 

If the id is a simple incremental integer and you add the entries in r and g in the same order, you can avoid the id at all and use the array indices instead:

# g = guesses g = [{ elmerxc2xad: 5, roger: 7, outcome: "Roger Win" }, {elmer: 5, roger: 1, outcome: "Elmer Win" }, { elmer: 4, roger: 8, outcome: "Roger Win" }] # r = actual results r = [{ elmer: 3, roger: 9, outcome: "Roger Win" }, {elmer: 7, roger: 9, outcome: "Roger Win" }, { elmer: 4, roger: 8, outcome: "Roger Win" }] # points table p = {}  # Loop over results. r.each_with_index { |result, id|   guess = g[id]    # Init a hash to store score   score = {}    # compute the score here   # ...    p[id] = score unless score.empty? } 

You can create a class to represent each entry of the array (let's call each entry a Match) and then implement the scoring algorithm as a method:

class Match   attr_accessor :elmer, :roger, :outcome    def initialize(elmer, roger, outcome)     @elmer = elmer     @roger = roger     @outcome = outcome   end    def compare(m)     score = 0      score = score + 1 if @outcome == m.outcome     score = score + 4 if @elmer == m.elmer and @roger == m.roger      score   end end 

Example usage:

guess = Match.new(5, 7, "Roger Win") result = Match.new(3, 9, "Roger Win") puts guess.compare(result) # => 1  guess = Match.new(5, 1, "Elmer Win") result = Match.new(7, 9, "Roger Win") puts guess.compare(result) # => 0  guess = Match.new(5, 7, "Roger Win") result = Match.new(5, 7, "Roger Win") puts guess.compare(result) # => 5  puts guess.compare(guess) # => 5 

If the string argument just says who is the winner based on the numbers, you can compute it:

class Match   attr_accessor :elmer, :roger    def initialize(elmer, roger)     @elmer = elmer     @roger = roger   end    def outcome     if @elmer > @roger       :elmer     elsif @roger > @elmer       :roger     else       :tie     end   end    def compare(m)     if @elmer == m.elmer and @roger == m.roger       5     elsif outcome == m.outcome       1     else       0     end   end end 

Example usage:

guess = Match.new(5, 7) result = Match.new(3, 9) puts guess.compare(result) # => 1  guess = Match.new(5, 1) result = Match.new(7, 9) puts guess.compare(result) # => 0  guess = Match.new(5, 7) result = Match.new(5, 7) puts guess.compare(result) # => 5  puts guess.compare(guess) # => 5  guess = Match.new(2, 2) result = Match.new(3, 3) puts guess.compare(result) # => 1  guess = Match.new(2, 2) result = Match.new(2, 2) puts guess.compare(result) # => 5 
 
 
         
         
1
 
vote

Suponiendo que sus listas ya están ordenadas por la identificación y contienen resultados / conjeturas para la misma ID que puede hacer:

  id4  

Esto reduce drásticamente el tiempo de ejecución desde el tiempo cuadrático hasta el tiempo lineal. Si aún no están ordenados, pero contienen exactamente las mismas identificaciones que puede hacer lo siguiente para ordenarlas.

  id5  
 

Assuming your lists are already sorted by the ID and contain results/guesses for exactly the same ID you can do:

r.zip(g).each do |result, guess|     score = {}     #... end 

This dramatically reduces runtime from quadratic to linear time. If they are not already sorted, but contain exactly the same IDs you can do the following to sort them.

r.sort_by! {|e| e[:id]} g.sort_by! {|e| e[:id]} 
 
 
1
 
vote

¿Cómo te mira esto?

  id6  

NOTA: Esto supone que G y R están ordenados por: ID; Si no, puede ordenar antes de hacer esto =) Además, definiría: id7 y id8

 

How does this look to you?

g.zip(r).collect do |guess, result|   points = (guess == result) ? 5 : guess[:outcome] == result[:outcome] ? 1 : 0      {:id => guess[:id], :points => points}  end 

Note: This assumes g and r are sorted by :id; if not, you can sort prior to doing this =) Also, I would define: FULL_SCORE = 5 and CORRECT_OUTCOME_SCORE = 1

 
 

Relacionados problema

8  IOS7 CHESSGAME UichessOarkView Design  ( Ios7 chessgame uichessboardview design ) 
He estado diseñando UichessboardView en la semejanza de UITYVIEW usando protocolos y delegados. uichessboardview.h @interface UIChessboardView : UIView...

5  Estructura de datos para entidades  ( Data structure for entities ) 
Estoy trabajando en un motor de componentes de la entidad-componente para juegos, que básicamente significa que una entidad es un objeto que apunta a los comp...

6  Sistema de eventos personalizado en C #  ( Custom event system in c ) 
Actualmente estoy escribiendo un juego y quiero codificar todo lo que sucede (GameObject se ha movido, HP cambió, fue creado / destruido, se ha creado / perdi...

6  Prototipo de javascript blackjack  ( Javascript blackjack prototype ) 
¿Cuál sería la mejor manera de organizar Blackjack en JavaScript y tal vez comience con la pizarra en blanco? Áreas específicas: Actualizando la UI Inc...

7  Mecánica de índice para tijeras de papel de roca  ( Index mechanics for rock paper scissors ) 
Acabo de pasar por un ejemplo en línea muy fácil Creando un juego de tijeras de rock-papel, pero parecía que no era un gran uso del poder de la computación. ...

5  Revisión de código para Hangman en C ++  ( Code review for hangman in c ) 
Tengo el siguiente programa C ++: autoConnect.py1 que se supone que replica visualmente el juego clásico de Hangman. ¿El código está totalmente optimiza...

4  Juego de Runas: Versión 3  ( Game of runes version 3 ) 
He escrito una versión muy revisada y desarrollada de la juego de runas . Los cambios principales se enumeran: Convertir runas para usar maldiciones. ag...

5  Mouselistener Lag en el juego de azulejos de piano  ( Mouselistener lag in piano tiles game ) 
Estaba intentando escribir mi propia versión simple de la aplicación de juegos de piano azulejos en Java, así como un ejercicio divertido. gamelogic.java ...

1  Piedra Papel tijeras  ( Rock paper scissors ) 
Gracias por su tiempo, soy nuevo en la programación y pasé algunos días haciendo este rock, papel y amp; Juego de tijera. ¿Qué otras mejoras posibles podrían ...

4  Atomas Clone en Python  ( Atomas clone in python ) 
Aquí está mi clon de mierda de atomas , un juego de rompecabezas donde combina pequeños átomos en otros más valiosos. 9988776655544337 ¿Hay algún códig...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos