hp12c
27 January 2012

RubyでCash Registerを解く-CodeEval

RubyでCash Registerを解く-CodeEval

ループで繰り返し引いて。丸め誤差の問題でちょっと..整数化してやったほうがいいの?

お釣りをコインとお札で。

#!/usr/bin/env ruby
COINS = {
 'PENNY' => 0.01,
 'NICKEL' => 0.05,
 'DIME' => 0.10,
 'QUARTER' => 0.25,
 'HALF DOLLAR' => 0.50,
 'ONE' => 1.00,
 'TWO' => 2.00,
 'FIVE' => 5.00,
 'TEN' => 10.00,
 'TWENTY' => 20.00,
 'FIFTY' => 50.00,
 'ONE HUNDRED' => 100.00
}
def cash_out(pp, ch)
 negative = ->i{ i < 0 }
 zero = ->i{ i.zero? }
 case ret = round_off(ch - pp)
 when negative; :ERROR
 when zero; :ZERO
 else count_coins(ret)
 end
end
def count_coins(ret)
 coins = COINS.values
 q = []
 while ret != 0.0
 if ret >= (try=coins.pop)
 q << try
 ret = round_off(ret - try)
 coins.push try
 end
 end
 q.map { |val| COINS.key val }.sort.join(',')
end
def round_off(f, n=2)
 (f*10**(n+1)).round/10.0**(n+1)
end
ARGF.lines do |line|
 pp, ch = line.split(';').map(&:to_f)
 puts cash_out(pp, ch)
end

Double Squaresを残してModerate終了。できそうもない..

RubyでPrime Numbersを解く-CodeEval

Enumeratorをtake_whileして。

指定数までの素数列。

#!/usr/bin/env ruby
def prime?(n)
 !(2..n/2).any? { |i| (n%i).zero? }
end
def prime_loop
 Enumerator.new { |y| n = 2; loop { y << n if prime?(n); n+=1 } }
end
ARGF.lines do |line|
 max = line[/\d+/].to_i
 puts prime_loop.take_while { |i| i < max }.join(',')
end

RubyでReverse and Addを解く-CodeEval

回文になるまでループして。

数字をひっくり返して足すことを繰り返して回文になる回数。

#!/usr/bin/env ruby
def palindrome(num)
 "#{num}" == "#{num}".reverse ? num : false
end
def reverse_add(num)
 num + "#{num}".reverse.to_i
end
ARGF.lines do |line|
 num = line[/-*\d+/].to_i
 cnt = 0
 begin
 num = reverse_add(num)
 cnt += 1
 end until ret = palindrome(num)
 printf "%d %d\n", cnt, ret
end

RubyでJolly Jumpersを解く-CodeEval

Array#each_consを使って。

並びの数字の差が3 2 1となってるものをJolly Jumperというらしい。

#!/usr/bin/env ruby
ARGF.lines do |line|
 n, *nums = line.scan(/\d+/).map(&:to_i)
 seq = nums.each_cons(2).inject([]) { |mem, cons| mem << cons.inject(:-).abs; mem }
 puts seq.all? { |i| n-=1; i == n } ? 'Jolly' : 'Not jolly'
end

RubyでArray Absurdityを解く-CodeEval

余計な条件がよくわからない..

数字列中の重複を見つける。

#!/usr/bin/env ruby
ARGF.lines do |line|
 next if line.chomp.empty?
 n, nums = line.split(';').map { |part| part[/,/] ? part.split(',').map(&:to_i) : part.to_i }
 next if nums.size != n or nums.any? { |i| !i.between?(0, n-2) }
 nums.sort.inject { |mem, i| mem == i ? puts(i) : mem = i }
end

RubyでEmail Validationを解く-CodeEval

本気じゃないよね?適当なところで。

メールアドレスの正規表現。

#!/usr/bin/env ruby
def valid_email?(str)
 email_regexp = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/
 str.match(email_regexp) ? :true : :false
end
ARGF.lines do |line|
 puts valid_email?(line.chomp)
end

RubyでNumber Pairsを解く-CodeEval

Array#combinationを使って。

数字列から合計が指定数になる数字のペアを見つける。

#!/usr/bin/env ruby
ARGF.lines do |line|
 nums, x = line.split(';').map do |part|
 part[/,/] ? part.split(',').map(&:to_i) : part.to_i
 end
 pairs = nums.combination(2).select { |a, b| a + b == x }
 puts pairs.empty? ? :NULL : pairs.map { |pair| pair.join(',') }.join(';')
end

RubyでTrailing Stringを解く-CodeEval

ワンライナーで:)

文字列中のサブ文字列を見つける。

#!/usr/bin/env ruby
ARGF.lines do |line|
 line.split(',').map(&:chomp).instance_eval { puts first[/#{last}$/] ? 1 : 0 }
end

RubyでDecimal To Binaryを解く-CodeEval

10進数を2進数に。

#!/usr/bin/env ruby
puts ARGF.map { |line| line[/\d+/].to_i.to_s(2) }

RubyでSum of integersを解く-CodeEval

ループで全組合せを作ってArray#max。

数字の並びにおける連続する数字群の最大値。

#!/usr/bin/env ruby
ARGF.lines do |line|
 nums = line.scan(/-*\d+/).map(&:to_i)
 candidates = []
 begin
 nums.inject(0) { |mem, i| candidates << mem += i; mem }
 end while nums.shift
 puts candidates.max
end

RubyでNumber of Onesを解く-CodeEval

String#countで。

数字の2進表現の1ビットの数。

#!/usr/bin/env ruby
puts ARGF.map { |line| line[/\d+/].to_i.to_s(2).count('1') }

RubyでEndiannessを解く-CodeEval

Array#packを使って。

システムのエンディアン。

#!/usr/bin/env ruby
def system_endian
 system, big, little = %w(s2 n2 v2).map { |ts| [1,2].pack ts }
 case system
 when big; :BigEndian
 when little; :LittleEndian
 end
end
puts system_endian

RubyでRemove Charactersを解く-CodeEval

String#deleteで。

文字列から指定文字を除く。

#!/usr/bin/env ruby
ARGF.lines do |line|
 if m = line.match(/^(.*),\s*(\w+)/) 
 str, scrubs = m.captures
 puts scrubs.chars.inject(str) { |s, chr| s.delete chr }
 end
end

RubyでFirst Non-Repeated Characterを解く-CodeEval

Enumerable#detectで。

文字列中の繰り返さない最初の文字。

#!/usr/bin/env ruby
ARGF.lines { |line| puts line.chars.detect { |chr| line.count(chr) == 1 } }

RubyでLowest Common Ancestorを解く-CodeEval

いやいやもっと簡単な方法があるはずだ。

バイナリーツリーの共通の親を見つける。

#!/usr/bin/env ruby
class Node
 attr_reader :label, :sub
 def initialize(label, *sub)
 @label = label
 @sub = sub
 end
end
def node
 ->label,*sub{ Node.new(label, *sub) }
end
def ancestors(label, tree, mem=[])
 ancestor = tree.label
 if ancestor == label
 mem
 else
 sub = tree.sub
 if sub.empty?
 [] 
 else
 sub.map { |s| ancestors(label, s, mem+[ancestor]) }
 end
 end.flatten
end
def find_lowest_common_ancestor(a, b, tree)
 (ancestors(a, tree) & ancestors(b, tree)).last
end
tree = node[30,
 node[8,
 node[3],
 node[20,
 node[10],
 node[29]
 ]
 ],
 node[52]
 ]
ARGF.lines do |line|
 a, b = line.scan(/\d+/).map(&:to_i)
 puts find_lowest_common_ancestor(a, b, tree)
end

RubyでMth to last elementを解く-CodeEval

アルファベットの並びにおける位置。

#!/usr/bin/env ruby
ARGF.lines do |line|
 *alpha, ns = line.split(/\s/)
 if ch=alpha[-ns.to_i]
 puts ch
 end
end

RubyでStack Implementationを解く-CodeEval

どうすりゃいいのか。

スタックを実装する。

#!/usr/bin/env ruby
class Stack
 def initialize
 @stack = []
 end
 def push(n)
 @stack += [n]
 end
 def pop
 @stack[-1].tap { @stack = @stack[0..-2] }
 end
end
ARGF.lines do |line|
 nums = line.scan(/\-?\d+/).map(&:to_i)
 st = Stack.new
 nums.each { |n| st.push n }
 loop do
 print "#{st.pop} "
 break puts unless st.pop
 end
end

RubyでPangramsを解く-CodeEval

Array#-を使って。

文字列がパングラムか判定する。

#!/usr/bin/env ruby
def pangram?(str)
 compo = str.scan(/\w/).map(&:downcase).uniq.sort
 deficits = [*'a'..'z'] - compo
 deficits.empty? ? 'NULL' : deficits.join
end
puts ARGF.map { |line| pangram?(line) }

RubyでDetecting Cyclesを解く-CodeEval

ループを使って。綺麗にかけない..

文字の並び中の繰り返しを見つける。

#!/usr/bin/env ruby
def find_cycles(nums)
 ns = nums.dup
 while top = ns.shift
 if pos = ns.index(top)
 first = ns[0...pos]
 second = ns[(pos+1)..(pos+first.size)]
 return [top, *first].join(' ') if first == second
 end
 end
 nil
end
ARGF.lines do |line|
 nums = line.scan(/\d+/).map(&:to_i)
 if cycle = find_cycles(nums)
 puts cycle
 end
end

RubyでLongest Linesを解く-CodeEval

ワンライナーで:)

先頭行の数だけ後続行から最長文字列を選ぶ。

#!/usr/bin/env ruby
puts ARGF.map(&:chomp).instance_eval { n=shift.to_i; sort_by{ |l| -l.size }.take(n) }


Please enable JavaScript to view the comments powered by Disqus. blog comments powered by Disqus
ruby_pack8

100円〜で好評発売中!
M'ELBORNE BOOKS



AltStyle によって変換されたページ (->オリジナル) /