I'm having a problem with my code, and can't seem to figure out what I need to change. Here are my three files, and at the bottom is the error that I am getting.
require './PokerHand'
require "./Constants"
require 'minitest/autorun'
class TestClass < MiniTest::Test
include Constants
def test_1
arr1 = [Card.new(2, "S"), Card.new(3, "S"),
Card.new(4, "S"), Card.new(5, "S"),
Card.new(6, "S")]
ph1 = PokerHand.new(arr1)
ph1.classify
assert_equal STRAIGHT_FLUSH, ph1.hand_type
end
def test_2
arr2 = [Card.new(9, "C"), Card.new(9, "S"),
Card.new(9, "H"), Card.new(9, "D"),
Card.new(11, "S")]
ph2 = PokerHand.new(arr2)
ph2.classify
assert_equal FOUR_OF_A_KIND, ph2.hand_type
end
def test_3
arr3 = [Card.new(4, "C"), Card.new(9, "S"),
Card.new(9, "H"), Card.new(9, "D"),
Card.new(9, "C")]
ph3 = PokerHand.new(arr3)
ph3.classify
assert_equal FOUR_OF_A_KIND, ph3.hand_type
end
new file Pokerhand.rb:
require "./Constants"
require "./Card"
require "./Deck"
require "./CardSpaceship"
class PokerHand < Deck
include Constants
attr_reader :hand_type
def initialize(the_cards)
#cards = [ ]
#hand_type = UNCLASSIFIED
for card in the_cards
#cards << card
end
end
# Determine hand type of PokerHand object.
def classify
#cards.sort!
# Straight flush
if #cards[0].rank == #cards[1].rank +1 &&
#cards[1].rank == #cards[2].rank +1 &&
#cards[2].rank == #cards[3].rank +1 &&
#cards[3].rank == #cards[4].rank +1 &&
#cards[0].suit == #cards[1].suit &&
#cards[1].suit == #cards[2].suit &&
#cards[2].suit == #cards[3].suit &&
#cards[3].suit == #cards[4].suit
#hand_type = STRAIGHT_FLUSH
end
end
new file test2.rb:
require './PokerHand'
require "./Constants"
require 'minitest/autorun'
class TestClass < MiniTest::Test
include Constants
def test_1
arr1 = [Card.new(2, "S"), Card.new(3, "S"),
Card.new(4, "S"), Card.new(5, "S"),
Card.new(6, "S")]
ph1 = PokerHand.new(arr1)
ph1.classify
assert_equal STRAIGHT_FLUSH, ph1.hand_type
end
getting error:
TestClass#test_1:
PokerHand.rb:145: warning: else without rescue is useless
C:/Ruby22/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require': JulianHansen_P5/PokerHand.rb:30: syntax error, unexpected tINTEGER, expecting keyword_then or ';' or '\n' (SyntaxError)
if #cards[0].rank == #cards[1].rank +1 &&
^
PokerHand.rb:31: syntax error, unexpected tINTEGER, expecting keyword_end
#cards[1].rank == #cards[2].rank +1 &&
The warning: else without rescue is useless warning is displayed when you setup an if/else statement improperly.
if true
puts 'hi''
end # end shouldn't be here
else
puts 'whoops'
end
You should find that in your code and correct it as well, although that isn't what is causing the fatal error.
The +1s in your if statement either need spaces or parentheses:
if #cards[0].rank == #cards[1].rank + 1 &&
or
if #cards[0].rank == (#cards[1].rank +1) &&
Related
I have a problem with transforming parsed JSON-like string, which contains nested arrays, to structured object. I am using parslet to do this.
I created parser and transformer, presented below. But I can't handle nested arrays situation.
require 'parslet'
class JSONLikeDataParser < Parslet::Parser
rule(:l_map_paren) {str('{')}
rule(:r_map_paren) {str('}')}
rule(:l_list_paren) {str('[')}
rule(:r_list_paren) {str(']')}
rule(:map_entry_delimiter) {str(':')}
rule(:val_delimiter) {str(',')}
rule(:quote) {str('"')}
rule(:simple_val) {match('[^",:\.\{\}\[\]]').repeat(1)}
rule(:quoted_val) {quote >> (quote.absnt? >> any).repeat(0) >> quote}
rule(:map) {l_map_paren >> map_entries.maybe.as(:map) >> r_map_paren}
rule(:map_entries) {map_entry >> (val_delimiter >> map_entry).repeat}
rule(:map_entry) {map_key >> map_entry_delimiter >> object}
rule(:map_key) {(match('[A-Za-z_]').repeat(1) >> match('[A-Za-z0-9_]').repeat).as(:key)}
rule(:list) {l_list_paren >> list_values.maybe.as(:list) >> r_list_paren}
rule(:list_values) {object >> (val_delimiter >> object).repeat}
rule(:object) {map | (simple_val | quoted_val).as(:value) | list }
root(:object)
end
#TODO doesn't handle properly nested array: [[[1,2],[3]]]
class JSONLikeDataTransform < Parslet::Transform
rule(map: subtree(:s)) do
ret = {}
if (s.is_a?(Hash))
ret[s[:key]] = s[:value]
else
s.each do |h|
ret.merge!(h)
end
end
OpenStruct.new(ret)
end
rule(key: simple(:k), value: simple(:v)) {{k.str => v.str}}
rule(key: simple(:k), list: simple(:v)) {{k.str => [v]}}
rule(key: simple(:k), list: sequence(:v)) {{k.str => v}}
rule(map: simple(:s)) {s ? OpenStruct.new(s) : OpenStruct.new}
rule(list: subtree(:s)) {[s]}
rule(list: sequence(:s)) {s}
rule(list: simple(:s)) {s ? [s] : []}
rule(value: subtree(:s)) {s}
rule(value: sequence(:s)) {s}
rule(value: simple(:s)) {s.str}
end
puts JSONLikeDataTransform.new.apply(JSONLikeDataParser.new.parse("[[[1],[2,3]]]")).inspect
Problematic string is "[[[1],[2,3]]]". I expect to receive properly nested structure. But what I get is "[[[[1],[2,3]]]]" one bracket too much.
Thanks everyone for sharing especially, #NigelThorne whose answer in other thread lead me to actual solution of this problem. I Introduced some additional classes like Map/Value/Arr so I am able to recognize whether particular array is created by Transform framework, or it is a result of list matching.
Below is a working code and some tests for future reference.
require 'parslet'
require 'parslet/convenience'
require 'ostruct'
module JSONLikeDataModule
module Parsing
class GobbleUp < Parslet::Atoms::Base
def initialize absent, min_chars = 0
#absent = absent
#min_chars = min_chars
end
def try(source, context, consume_all)
excluding_length = source.chars_until(#absent)
if excluding_length >= #min_chars
return succ(source.consume(excluding_length))
else
return context.err(self, source, "No such string in input: #{#absent.inspect}.")
end
end
def to_s_inner(prec)
"until('#{#absent}')"
end
end
class JSONLikeDataParser < Parslet::Parser
rule(:l_map_paren) {str('{')}
rule(:r_map_paren) {str('}')}
rule(:l_list_paren) {str('[')}
rule(:r_list_paren) {str(']')}
rule(:map_entry_delimiter) {str(':')}
rule(:val_delimiter) {str(',')}
rule(:quote) {str('"')}
rule(:simple_val) {match('[^",:\.\{\}\[\]]').repeat(1)}
rule(:quoted_val) {quote >> GobbleUp.new('"').as(:value) >> quote}
rule(:map) {l_map_paren >> map_entries.maybe.as(:map) >> r_map_paren}
rule(:map_entries) {map_entry >> (val_delimiter >> map_entry).repeat}
rule(:map_entry) {map_key >> map_entry_delimiter >> object}
rule(:map_key) {(match('[A-Za-z_]').repeat(1) >> match('[A-Za-z0-9_]').repeat).as(:key)}
rule(:list) {l_list_paren >> list_values.maybe.as(:list) >> r_list_paren}
rule(:list_values) {object >> (val_delimiter >> object).repeat}
rule(:object) {map.as(:value) | simple_val.as(:value) | quoted_val | list.as(:value)}
root(:object)
end
class JSONLikeDataTransform < Parslet::Transform
rule(key: simple(:key), value: simple(:value)) {{builder.value(key) => builder.value(value)}}
rule(map: subtree(:s)) do
ret = {}
next builder.map(ret) unless s
to_transform = s
if to_transform.is_a?(Hash)
to_transform = [to_transform]
end
to_transform.each do |h|
ret.merge!(h)
end
builder.map(ret)
end
rule(list: simple(:list)) {builder.list(list)}
rule(list: sequence(:list)) {builder.list(list)}
rule(list: subtree(:list)) {builder.list(list)}
rule(value: simple(:value)) {builder.value(value)}
rule(value: sequence(:value)) {value.map {|val| builder.value(val)}}
rule(value: subtree(:value)) {builder.value(value)}
end
class Builder
def map(h)
Map.new(h)
end
def list(l)
Arr.new(l)
end
def value(v)
Value.new(v)
end
class Arr
def initialize(val)
#val = val
end
def val
return [] unless #val
return #val.map(&:val) if #val.is_a?(Array)
return [#val.val]
end
end
class Map
def initialize(val)
#val = val
end
def val
return OpenStruct.new unless #val
#val.inject(OpenStruct.new) do |ostruct, (k,v)|
ostruct[k.val] = v.val
ostruct
end
end
end
class Value
def initialize(val)
#val = val
end
def val
#val.respond_to?(:str) ? #val.str : #val.val
end
end
end
end
end
module JSONLikeDataModule
class JSONLikeDataFactory
##flag_data_parser ||= Parsing::JSONLikeDataParser.new
##flag_data_transform ||= Parsing::JSONLikeDataTransform.new
class << self
private :new
def create(flag_data_str)
parsed_tree = ##flag_data_parser.parse_with_debug(flag_data_str)
ret = ##flag_data_transform.apply(parsed_tree, :builder => Parsing::Builder.new)
ret.val
end
end
end
end
Tests
require 'minitest/autorun'
class JSONLikeFactoryTest < Minitest::Test
include JSONLikeDataModule
describe "JSONLikeDataFactory" do
subject do
JSONLikeDataFactory
end
it "should create string val" do
subject.create('_S').must_equal "_S"
end
it "should create empty array" do
subject.create('[]').must_equal []
end
it "should create empty nested array" do
subject.create('[[[]]]').must_equal [[[]]]
end
it "should create not empty nested array" do
subject.create('[[[1],[2,3]]]').must_equal [[['1'],['2','3']]]
end
it "should create empty OpenStruct" do
subject.create('{}').must_equal OpenStruct.new
end
it "should create filled 1level OpenStruct" do
subject.create('{key1:val,key2:"val"}').must_equal OpenStruct.new(key1: "val", key2: "val")
end
it "should create filled 2levels OpenStruct" do
subject.create('{key1:val,key2:"val",key3:{},key4:{key1:val},key5:[1,2],key6:[[1,2,3],{},1,{key1:"[]{}:,."}]}').must_equal o(key1: "val", key2: "val", key3: o, key4: o(key1: "val"), key5: %w(1 2), key6: [%w(1 2 3), o, '1', o(key1: '[]{}:,.')])
end
def o(h= {})
OpenStruct.new(h)
end
end
end
got this error but cant figure out where i need to put an end.
test/test1:54: class definition in method body
test/test1:79: syntax error, unexpected end-of-input, expecting keyword_end
class Code
attr_reader :pegs
def initialize(pegs)
##pegs_key = { "R" => :red,"G" => :green,"B" => :blue,"Y" => :yellow,
"O" => :orange,"P" => :purple }
#pegs = pegs
end
class << self
def random
rand_pegs_set = []
4.times { rand_pegs_set << ##pegs_Key.values.sample }
Code.new(rand_pegs_set)
end
def parse(str)
str = string.split("")
pegs_set = []
str.each do |letter|
if ##pegs_key.has_key?(letter.upcase)
pegs_set << ##pegs_key[letter.upcase]
else
raise "Incorrect colors"
end
end
Code.new(pegs_set)
end
end
def exact_matches(guess)
matches = 0
pegs_set.each_with_index { |color,i| matches += 1 if self[i] == color }
matches
end
def color_counter
counter = Hash.new(0)
#pegs.each { |color| counter[color] += 1 }
counter
end
def near_matches(guess)
matches = 0
code_counter = self.color_counter
guess.color_counter.each do |color,count|
if code_counter.has_key?(color)
if code_counter[color] > count ? matches += count : matches += code_counter[color]
end
matches - self.exact_matches(guess)
end
end
class Game
attr_reader :secret_code
def initialize(secret_code = Code.random)
#secret_code = secret_code
end
def play
10.times do
puts "Enter your guess"
guess = Code.parse(gets.chomp)
if guess == #secret_code
puts "Great Job! you got it"
break
end
show_matches(guess)
end
end
def show_matches(guess)
exact_matches = #secret_code.exact_matches(guess)
near_matches = #secret_code.near_matches(guess)
puts "#{exact_matches} were exactly right"
puts "#{near_matches} were nearly a match"
end
end
Make
if code_counter[color] > count ? matches += count : matches += code_counter[color]
so
matches += (code_counter[color] > count ? count : code_counter[color])
I am banging my head against the error message I keep getting, reading that "syntax error, unexpected keyword_end, expecting end-of-input." I cannot find my mistake for the life of me. It's probably sloppy-looking, I am a newbie. And any tips on preventing this specific issue in the future would also be greatly appreciated!
$move_direction_hash = {"N" => [0,1], "E" => [1,0], "S" => [0,-1], "W" => [-1,0]}
$cardinal_directions = ["N", "E", "S", "W"]
class Martian
attr_accessor :coordinate_x, :coordinate_y, :bearing, :direction_string
def initialize (coordinate_x, coordinate_y, bearing, direction_string)
#coordinate_x = coordinate_x
#coordinate_y = coordinate_y
#bearing = bearing
#direction_string = direction_string
end
def check_valid
#coordinate_x.between?(0, $boundaries[0]) && coordinate_y.between?(0, $boundaries[1])
return true
end
end
#will be second and last called in source code
def get_final
return "#{coordinate_x} #{coordinate_y} #{bearing}"
end
def move_forward
# find where in the hash the bearing is
position_array = $move_direction_hash[#bearing]
# returns a temporary variable
# that is the
test_x = #coordinate_x + position_array[0]
test_y = #coordinate_y + position_array[1]
if $rovers_on_grid.include?([test_x.to_s, test_y.to_s])
puts "Stopping Martian. You're about to crash!"
get_final
break
else
#coordinate_x = test_x
#coordinate_y = test_y
if check_valid == false
puts "Stopping Martian. About to run off the plateau."
get_final
break
else
return #coordinate_x, #coordinate_y
end
end
end
def add_to_grid
$rovers_on_grid << [#x_coordinate, #y_coordinate]
end
def read_instructions
#direction_string.each_char do |direction|
if direction == "L" || direction == "R"
position = $cardinal_directions.index(#bearing)
if direction == "L"
position = (position - 1)%4
$cardinal_directions[position]
elsif direction == "R"
position = (position + 1)%4
$cardinal_directions[position]
else
puts "Error!"
end
#bearing = $cardinal_directions[position]
elsif direction == "M"
move_forward
end
end
end
end
This error is located in the check_valid method. You missed the if.
def check_valid
if #coordinate_x.between?(0, $boundaries[0]) && coordinate_y.between?(0, $boundaries[1])
return true
end
end
Like steenslag mentioned the if statement is not required. You can write:
def check_valid
return #coordinate_x.between?(0, $boundaries[0]) && coordinate_y.between?(0, $boundaries[1])
end
I'm getting the error:
minesweeper.rb:32:in '|': can't convert Fixnum into Array (TypeError)
from minesweeper.rb:32:in 'block in create_hint_board'
from minesweeper.rb:31:in 'each_index'
from minesweeper.rb:31:in 'create_hint_board'
from minesweeper.rb:68:in '(main)'
when attempting to check a 2D array for a value, and adding 1 to all cells adjacent to that index location. The error occurs at subarray2 = board|i|. I'm trying to iterate over the entire 2D array
The entire code is
#def load_board(file)
# gameboard = File.readlines(file)[1..-1]
# gameboard.map! do |line|
# line.split.map(&:to_s)
# end
# $globalarray = gameboard
#end
$globalarray = [['*','.','.','.'],['.','.','*','.'],['.','.','.','.']]
def pp_board(board)
puts Array.new(board[0].size*2+1, '-').join('')
board.each do |row|
puts "|" + row.join("|") + "|"
puts Array.new(row.size*2+1, '-').join('')
end
end
def create_hint_board(board)
board = $globalarray
$globalarray.each_index do |i|
subarray = $globalarray[i]
subarray.each_index do |j|
if $globalarray[i][j] != '*'
board[i][j].to_i
board[i][j] = 0
end
puts "#{String(i)},#{String(j)} is #{board[i][j]}"
end
end
board.each_index do |i|
subarray2 = board|i|
subarray2.each_index do |j|
if board[i][j] == '*'
board[i+1][j] = board[i+1][j]+1
board[i+1][j+1] = board[i+1][j+1]+1
board[i+1][j-1] = board[i+1][j-1]+1
board[i][j-1] = board[i][j-1]+1
board[i][j+1] = board[i][j+1]+1
board[i-1][j] = board[i-1][j]+1
board[i-1][j+1] = board[i-1][j+1]+1
board[i-1][j-1] = board[i-1][j-1]+1
end
end
end
puts "new array is "
puts board
end
=begin
#def copy_to_blank(board)
# $newarrayblank = $newarray
# $newarrayblank.each_index do |i|
# subarray = $newarrayblank[i]
# subarray.each_index do |j|
# $newarrayblank[i][j] = '.'
# puts "#{String(i)},#{String(j)} is #{$newarrayblank[i][j]}"
# end
# end
#end
#load_board("mines.txt")
blank = [[]]
=end
puts "Original array is"
puts $globalarray
create_hint_board($globalarray)
#pp_board($globalarray)
#create_hint_board($globalarray)
#puts "new array is"
#pp_board($newarray)
#puts "new blank board is"
#copy_to_blank(blank)
#puts $newarrayblank
#pp_board($newarrayblank)
=begin
puts "Input Guess"
value1 = gets.split(" ")
row_guess = value1[0].to_i
col_guess = value1[1].to_i
puts $newarray[row_guess][col_guess]
while $newarray[row_guess][col_guess] != '*'
if $newarray[row_guess][col_guess] != '*'
puts "You guessed row #{row_guess} and column #{col_guess}."
puts $newarray[row_guess][col_guess]
#$newarrayblank[row_guess][col_guess] = $newarray[row_guess][col_guess]
#pp_board($newarrayblank)
puts "Input your guess in coordinates, separated by a blank space, or press q to quit."
value1 = gets.split(" ")
row_guess = value1[0].to_i
col_guess = value1[1].to_i
elsif $newarray[row_guess][col_guess] == '*'
puts "You guessed row #{row_guess} and column #{col_guess}."
puts "You hit a mine!"
puts "Game Over"
end
end
=end
The area giving me trouble is
board.each_index do |i|
subarray2 = board|i|
subarray2.each_index do |j|
if board[i][j] == '*'
board[i+1][j] = board[i+1][j]+1
board[i+1][j+1] = board[i+1][j+1]+1
board[i+1][j-1] = board[i+1][j-1]+1
board[i][j-1] = board[i][j-1]+1
board[i][j+1] = board[i][j+1]+1
board[i-1][j] = board[i-1][j]+1
board[i-1][j+1] = board[i-1][j+1]+1
board[i-1][j-1] = board[i-1][j-1]+1
end
end
end
I've also tried moving the addition section above, as an elsif statement below the if, like so
def create_hint_board(board)
board = $globalarray
$globalarray.each_index do |i|
subarray = $globalarray[i]
subarray.each_index do |j|
if $globalarray[i][j] != '*'
board[i][j].to_i
board[i][j] = 0
elsif board[i][j] == '*'
board[i+1][j] = board[i+1][j]+1
board[i+1][j+1] = board[i+1][j+1]+1
board[i+1][j-1] = board[i+1][j-1]+1
board[i][j-1] = board[i][j-1]+1
board[i][j+1] = board[i][j+1]+1
board[i-1][j] = board[i-1][j]+1
board[i-1][j+1] = board[i-1][j+1]+1
board[i-1][j-1] = board[i-1][j-1]+1
end
end
puts "#{String(i)},#{String(j)} is #{board[i][j]}"
end
end
This results in the error message:
minesweeper.rb:28:in '+': can't convert Fixnum into String (TypeError)
from minesweeper.rb:28:in 'block (2 levels) in create_hint_board'
from minesweeper.rb:28:in 'each_index'
from minesweeper.rb:28:in 'block in create_hint_board'
from minesweeper.rb:28:in 'each_index'
from minesweeper.rb:28:in 'create_hint_board'
from minesweeper.rb:28:in '(main')
The issue is at following line
subarray2 = board|i|
You are doing:
board.each_index do |i|
And in following line you are trying to get the value of board at that index. To achive this you should do:
subarray2 = board[i]
At last, there is a better way to achieve this by using each_with_index.
Eg:
board.each_with_index do |v, i|
subarray2 = v
...
end
i am just starting my journey with ruby and am very new to programming in general as well. This is code for a homework assignment. I am getting syntax error as described in title. I understand that I have added some extra end while end of file was expected? right?
but where is this extra "end".
The code:
class WrongNumberOfPlayersError < StandardError ; end
class NoSuchStrategyError < StandardError ; end
def rps_result(move1,move2)
if (move1 == "r" && move2 == "s") || (move1 == "s" && move2 == p) || (move1 == "p" && move2 == "r")
return true
else
return false
end
end
def rps_game_winner(player1, player2)
strategy = /[rps]/
raise NoSuchStrategyError unless (move1 =~ strategy) & (move2 =~ strategy)
move1 = player1[1].downcase
move2 = player2[2].downcase
rps_result(move1, move2)? player1 : player2
end
end
def rps_tournament_winner(game)
round_winners = []
if game.length < 2
raise WrongNumberOfPlayersError
else
game.each_slice(2) do
|l1 , l2|
round_winners << rps_game_winner(l1, l2)
end
rps_tournament_winner(round_winners)
end
end
rps_tournament_winner([[[["Richard", "S"], ["Dave", "S"]], [["Richard", "R"], ["Michael", "S"]]], [[["Allen", "S"], ["Omer", "P"]], [["David E.", "R"], ["Richard X.", "P"]]]])
The rps_result method is never closed. Move the second end at the end of rps_game_winner to the last intended line of the rps_result method.
P.s. sorry for all the end's :)
I have modified the second block of code. Please check if it works.
def rps_game_winner(player1, player2)
strategy = /[rps]/
raise NoSuchStrategyError unless (move1 =~ strategy) && (move2 =~ strategy)
move1 = player1[1].downcase
move2 = player2[2].downcase
rps_result(move1, move2) ? player1 : player2
end
def rps_tournament_winner(game)
round_winners = []
if game.length < 2
raise WrongNumberOfPlayersError
else
game.each_slice(2) do |l1 , l2|
round_winners << rps_game_winner(l1, l2)
end
rps_tournament_winner(round_winners)
end
end
rps_tournament_winner([[[["Richard", "S"], ["Dave", "S"]], [["Richard", "R"], ["Michael", "S"]]], [[["Allen", "S"], ["Omer", "P"]], [["David E.", "R"], ["Richard X.", "P"]]]])
Did 4 changes:
Removed extra end in rps_game_winner method.
Added space between tertiary operators in rps_game_winner method.
rps_game_winner method, 2nd line, unless condition had only one &.
In rps_tournament_winner method, moved the args |l1, l2| after do.