第26回 Ruby/Rails勉強会@関西に参加
日本Rubyの会 公式Wiki - 第26回 Ruby/Rails勉強会@関西
http://jp.rubyist.net/?KansaiWorkshop26
遅くなったが、Ruby初級者向けレッスン by okkezさんの回答だけでも貼っとこう。そういえば、前々回の分が、okkezさんに添削されていたのだった。今更ですがありがとうございます。気付かなくて申し訳なかったです。
勉強会の内容については、
- Rack, nginx, thinが面白そうなので、調べたい。
- ujihisaさんの発表で出たvimscriptだが、vimscriptからRubyを使うことが出来るのか。emacs(elisp)からRubyが使えたりもするのだろうか。elispなんか全く分からないが。ちょっと調べた感じでは情報が見つからない・・・。
という感じでした。
1. ナベアツ問題
Macだと簡単にしゃべらせることが出来るようだ。楽しそう。でも、windowsでがんばってしゃべらせる気にはならないなあ。
MIN = 1 MAX = 100 class Nabeatsu def perform(min, max) min.upto(max) do |i| speech = "" speech << "Aho" if should_be_idiot?(i) speech << "Meaow" if should_be_animal?(i) speech << i.to_s if speech == "" puts speech end end def should_be_idiot?(num) num % 3 == 0 || num.to_s =~ /3/ end def should_be_animal?(num) num % 5 == 0 end end Nabeatsu.new.perform(MIN, MAX)
2. Bottles of Beer on the Wall
残りボトルが無くなった時に歌詞が変わるのに最初気付かなかった。
class Song @@initial_bottle_num = 99 @@lyrics = ["%s of beer on the wall", "%s of beer", "Take one down and pass it around", "%s of beer on the wall"] @@third_line_for_last = "There are no more to pass around" @remaining_bottle_num = 0 def initialize @remaining_bottle_num = @@initial_bottle_num end def sing_all sing sing_all if 0 <= @remaining_bottle_num end def sing num = bottle_count(@remaining_bottle_num) remain = bottle_count(@remaining_bottle_num - 1) lyrics = @@lyrics lyrics[2] = @@third_line_for_last if @remaining_bottle_num <= 0 printf(lyrics.join("\n") + "\n\n", num, num, remain) @remaining_bottle_num = @remaining_bottle_num - 1 end private def bottle_count(num) case when num <= 0 num = "No more bottles" when num == 1 num = num.to_s + " Bottle" else num = num.to_s + " Bottles" end end end song = Song.new.sing_all
3. 石取りゲーム
長い!!考え過ぎだろう。ROBOT_SELFISH_RATEの率で、スタート時の石の数が先手が勝つ個数で、かつプレイヤーが先手を選んだ時に、ゴネて自分を先手にする。また、ROBOT_MISTAKE_RATEの率で、相手が勝つような残り個数の時に、ミスって負けに転じる数を取る。0にすると全くミスらない。
require "observer" module GameLogic def take(stone_count) if win?(stone_count) #取る数毎に、勝つか負けるかを取得 max_takable = [MAX_TAKABLE_STONE, stone_count].min wins_or_loses = (1..max_takable).to_a.inject({:wins => [], :loses => []}) do |h, i| win?(stone_count - i) ? h[:wins] << i : h[:loses] << i h end if rand < ROBOT_MISTAKE_RATE #負ける方を選択 wins_or_loses[:wins][rand(wins_or_loses[:wins].size)] else #勝つ方を選択 wins_or_loses[:loses][rand(wins_or_loses[:loses].size)] end else take_random(stone_count) end end def win?(stone_count) stone_count % (MAX_TAKABLE_STONE + 1) != 1 end def robot_selfish?(stone_count) win?(stone_count) && rand <= ROBOT_SELFISH_RATE end def take_random(stone_count) rand([MAX_TAKABLE_STONE, stone_count].min) + 1 end def takable?(num, stone_count) !num.nil? && 0 < num.to_i && num.to_i <= [MAX_TAKABLE_STONE, stone_count].min end def continue?(input) !input.nil? && (input == "y" || input == "Y") end end class State include GameLogic attr_accessor :result, :stone_count, :players_turn, :player_last_took, :robot_last_took def initialize(state = nil) if !state.nil? @result =state.result @stone_count = state.stone_count @players_turn = state.players_turn @player_last_took = state.player_last_took @robot_last_took = state.robot_last_took end end end class InitialState < State def apply(input = nil) @stone_count = rand(MAX_STONE_COUNT - MIN_STONE_COUNT) + MIN_STONE_COUNT + 1 @result = :greeting SelectTurnState.new(self) end end class SelectTurnState < State def apply(input = nil) @players_turn = input.to_i @players_turn = nil if @players_turn != 1 && @players_turn != 2 if @players_turn.nil? @result = :select_turn self else selfish = robot_selfish?(@stone_count) if selfish && @players_turn == 1 @players_turn = 2 @result = :selfish_turn_determination else @result = :turn_determination end TurnDeterminationState.new(self) end end end class TurnDeterminationState < State def apply(input = nil) @player_last_took = nil @robot_last_took = nil if @players_turn == 2 @robot_last_took = take(@stone_count) @stone_count = @stone_count - @robot_last_took end @result = :take_stone PlayState.new(self) end end class PlayState < State def apply(input = nil) @player_last_took = nil @robot_last_took = nil if takable?(input, @stone_count) @player_last_took = input.to_i @stone_count = @stone_count - @player_last_took if @stone_count <= 0 @result = :game_over_player_lost GameOverState.new(self) else @robot_last_took = take(@stone_count) @stone_count = @stone_count - @robot_last_took if @stone_count <= 0 @result = :game_over_player_won GameOverState.new(self) else @result = :take_stone self end end else @result = :take_stone_error self end end end class GameOverState < State def apply(input = nil) if continue?(input) @result = :restart InitialState.new(self) else @result = nil nil end end end class TextUi attr_accessor :game, :response def initialize(game) @game = game @game.add_observer(self) @response = TextResponse.new end def update(state) print @response.render(state) @game.update(gets.strip) end end class TextResponse def render(state) send(state.result.to_s, state) unless state.result.nil? end def greeting(state) "石の数は #{state.stone_count} 個です。\n" + "先手/後手を選択してください。(1:先手/2:後手)>" end def select_turn(state) "先手/後手を選択してください。(1:先手/2:後手)>" end def turn_determination(state) sprintf "あなたは %s です。何か押すとスタートします。>", state.players_turn == 1 ? "先手" : "後手" end def selfish_turn_determination(state) "ダメです。あなたは後手です。何か押すとスタートします。>" end def take_stone(state) stone_count(state) + takable_stones + ">" end def take_stone_error(state) remaining_stone_count(state) + takable_stones + ">" end def game_over_player_won(state) stone_count(state) + "\nあなたの勝ちです。もう一回やりますか?(y:もう一回/n:終了)>" end def game_over_player_lost(state) stone_count(state) + "\n私の勝ちです。もう一回やりますか?(y:もう一回/n:終了)>" end def restart(state) "何か押すと最初から始めます>" end private def takable_stones sprintf "何個取りますか?(%s)", (1..MAX_TAKABLE_STONE).to_a.join("/") end def stone_count(state) res = player_took(state) robot_took = robot_took(state) res += res != "" && robot_took != "" ? " / " + robot_took : robot_took res += res != "" ? " 取りました。" : "" res += remaining_stone_count(state) end def player_took(state) state.player_last_took.nil? ? "" : "あなた: #{state.player_last_took} 個" end def robot_took(state) state.robot_last_took.nil? ? "" : "私: #{state.robot_last_took} 個" end def remaining_stone_count(state) "残り #{state.stone_count} 個です。" end end class Game include Observable attr_accessor :state def initialize @state = InitialState.new end def start update(nil) end def update(input) @state = @state.apply(input) if @state.nil? exit else changed notify_observers(@state) end end end MIN_STONE_COUNT = 10 MAX_STONE_COUNT = 100 MAX_TAKABLE_STONE = 3 ROBOT_SELFISH_RATE = 0.7 ROBOT_MISTAKE_RATE = 0.1 game = Game.new ui = TextUi.new(game) game.start
今他の人達のエントリ見たら、なんかみんな短いな。