なんじゃくにっき

プログラミングの話題中心。

クックパッドマートのエンジニア採用試験の問題を解く

ちょっとバズってたクックパッドマートの採用試験の問題を秋の夜長に解いてみました。

言語はRuby

3問中1問だけ。

↓のQ2です。

cookpad-mart-careers.studio.site

問題の趣旨

問題文は上のリンク先で確認してもらうとして、 趣旨としては、要素の並べ替え問題なのだが、 要素同士の順位はネットワーク越しにAPI経由しか取れないし、一度にわかるのは2つの要素の順位の大小だけ。

こういったときに効率よく並べ替えをどうするか、 要はAPIを叩く回数を減らすにはどうするかというのが中心の問題。

あとはエラー時のハンドリングなどを見るものと思われる。

ソースコード

toybox/solve.rb at 263acef1105f5e0461a59b2940ed75351aa905c5 · nanjakkun/toybox · GitHub

require "net/http"
require "json"

class Monster
  include Comparable 

  URI_ROOT = "https://ob6la3c120.execute-api.ap-northeast-1.amazonaws.com/Prod/battle/"

  def initialize(name:)
    @name = name
  end

  def to_s
    @name
  end

  def <=>(that)
    uri = URI.parse("#{URI_ROOT}#{self}+#{that}")

    # response example: {"winner":"dragon","loser":"griffin"}
    response = Net::HTTP.get_response(uri)

    if response.code.to_i != 200
      raise "status code is #{response.code}"
    end

    res = JSON.parse(response.body)

    # puts res
    
    res['winner'] == @name ? 1 : -1
  end
end

arr = ARGV.map{|arg| Monster.new(name: arg)}

puts arr.sort.reverse.map(&:to_s).join(' ')

ちょっとだけ自分で解説

最適解ではない、です。

この手の問題だと、自分で最も効率の良い(と思った)ソートアルゴリズムを実装したくなるかもしれないが、

標準ライブラリのArray#sortを使いました。

Comparableをincludeして<=>メソッドを実装すればsortできます。

<=>の中でAPIコールしてどちらが大きいか返せばOK。

module Comparable (Ruby 2.7.0 リファレンスマニュアル)

sortの中身が分からずに使うの気持ち悪いとか思うかもしれないですが

(大体の言語の実装系ではソートアルゴリズム指定しない場合はクイックソートで、要素数少ないときだけ別のを入れてるパターンが多い気がする)

任せてしまってもそんなに悪くないんじゃないかと。

実際いくつかのパターンで、自分で書いたクイックソートに置き換えて試してみましたがAPIコール数は同じでした(全部試したわけではないので違うケースもあるかもしれない)。

コード量多くなる割に効果がないのでその部分は消しましたが。

他、APIの結果キャッシュが要ると思うかもしれないですが、試した限りでは同じものが2度以上呼ばれていなかったので実装しませんでした。

所感

問題中に示されているURI、実際に叩けるんですね。 AWS LambdaとAmazon API Gatewayで出来ているんでしょうか。