ひがきの日記

2018-03-23

桜川本店4個セットの組み合わせ

大阪カヌレ専門店カヌレ堂ステマ企画 第3弾。

堂島店ではホワイトデー需要も終わり落ち着きを取り戻した感があるが、桜川本店では相変わらず春休み需要に沸いているようだ。

Instagram桜川4個セットを投稿している人がいて、桜川店での4個セット価格が570円と判明した。

堂島店に引き続き桜川本店も 4個セットの組み合わせを表示してみる。

menu = <<EOF.lines.map{|l| l.chomp.split(/\s+/)}.each_with_object({}){|(v,k), _| _[k] = v.to_i}
120 しろ
130 ほうじ茶
130 抹茶あんこ
130 黒糖くるみ
150 珈琲
140 あんず
160 ベリーベリー
170 ばなナッツ
EOF

price = 570

combinations = menu.keys.combination(4).to_a
set4p = combinations.select{|caneles| caneles.map{|c| menu[c]}.sum == price}
  .select{|caneles| seasons.any?{|season| caneles.include?(season)}}
  .reject{|caneles| seasons.all?{|season| caneles.include?(season)}}

set4p.size                      # => 10
combinations.size               # => 70

set4p
# => [["しろ", "ほうじ茶", "珈琲", "ばなナッツ"],
#     ["しろ", "抹茶あんこ", "珈琲", "ばなナッツ"],
#     ["しろ", "黒糖くるみ", "珈琲", "ばなナッツ"],
#     ["しろ", "珈琲", "あんず", "ベリーベリー"],
#     ["ほうじ茶", "抹茶あんこ", "珈琲", "ベリーベリー"],
#     ["ほうじ茶", "抹茶あんこ", "あんず", "ばなナッツ"],
#     ["ほうじ茶", "黒糖くるみ", "珈琲", "ベリーベリー"],
#     ["ほうじ茶", "黒糖くるみ", "あんず", "ばなナッツ"],
#     ["抹茶あんこ", "黒糖くるみ", "珈琲", "ベリーベリー"],
#     ["抹茶あんこ", "黒糖くるみ", "あんず", "ばなナッツ"]]

全8種を使用していたが、頻度はバラバラだった。

caneles = set4p.flatten.sort
caneles.uniq.size    # => 8

puts menu.keys.map{|c| "%4d %s" % [caneles.count(c), c]}
# >>    4 しろ
# >>    5 ほうじ茶
# >>    5 抹茶あんこ
# >>    5 黒糖くるみ
# >>    7 珈琲
# >>    4 あんず
# >>    4 ベリーベリー
# >>    6 ばなナッツ

2018-03-19

【訂正】ホワイトデーの組み合わせ

ホワイトデーも終わり、そろそろカヌレ堂も落ち着くかと思いきや、春休みということで連日賑わっているようだ。

前回「ホワイトデー4個セットの組み合わせを洗い出す」に間違いがあることが分かった。

カヌレ堂では、毎月フレーバーの変わる 1ヶ月限定のカヌレが存在する。

4個セットには必ず限定カヌレのどちらか 1つが入っていたらしい。*1

4個セットの組み合わせは以下のように訂正する。

seasons = %w[ベリーベリー ばなナッツ]

combinations = menu.keys.combination(4).to_a
set4p = combinations.select{|caneles| caneles.map{|c| menu[c]}.sum == price}
  .select{|caneles| seasons.any?{|season| caneles.include?(season)}}
  .reject{|caneles| seasons.all?{|season| caneles.include?(season)}}

set4p.size                      # => 8
combinations.size               # => 70

set4p
# => [["しろ", "くろ", "千葉落花生", "ばなナッツ"],
#     ["しろ", "ほうじ茶キャラメル", "千葉落花生", "ばなナッツ"],
#     ["しろ", "きなこ五穀", "千葉落花生", "ベリーベリー"],
#     ["しろ", "抹茶ピスタチオ", "千葉落花生", "ベリーベリー"],
#     ["くろ", "ほうじ茶キャラメル", "きなこ五穀", "ばなナッツ"],
#     ["くろ", "ほうじ茶キャラメル", "抹茶ピスタチオ", "ばなナッツ"],
#     ["くろ", "きなこ五穀", "抹茶ピスタチオ", "ベリーベリー"],
#     ["ほうじ茶キャラメル", "きなこ五穀", "抹茶ピスタチオ", "ベリーベリー"]]

カヌレ 4個の合計が 600円になる組み合わせは 8通りに減った。

caneles = set4p.flatten.sort
caneles.uniq.size    # => 8

puts menu.keys.map{|c| "%4d %s" % [caneles.count(c), c]}
# >>    4 しろ
# >>    4 くろ
# >>    4 ほうじ茶キャラメル
# >>    4 きなこ五穀
# >>    4 抹茶ピスタチオ
# >>    4 千葉落花生
# >>    4 ベリーベリー
# >>    4 ばなナッツ

しかし、全8種が使われており、使用頻度も均等であった。

*1:両方入ることはないだろう。

2013-02-09

解答例 ─ Ruby初級者向けレッスン 44回

第56回 Ruby/Rails勉強会@関西 での Ruby初級者向けレッスン 44回 の解答例 *1

演習問題 1

0 から 9 までの数値をもつ配列 a がある。
a = (0..9).to_a
a # => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  1. 各要素を順番に表示しよう。
  2. 各要素を 2倍した値を持つ配列を作ろう。
  3. 全要素の合計値を計算しよう。
  • スライドのおさらい。
  • 改めてやってみると、意外とできないかも知れないよ。
# -*- coding: utf-8; -*-

# 0 から 9 までの数値をもつ配列 a がある。
a = (0..9).to_a         # => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


# 各要素を順番に表示しよう
a.each{|i| puts i}

# >> 0
# >> 1
# >> 2
# >> 3
# >> 4
# >> 5
# >> 6
# >> 7
# >> 8
# >> 9


# 各要素を 2倍した値を持つ配列を作ろう
a.map{|i| i * 2}  # => [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]


# 全要素の合計値を計算しよう
a.inject{|s, i| s + i}      # => 45

## マニアが書くと
a.inject(:+)                # => 45

演習問題 2

0 から 9 までの数値をもつ配列 a がある。
  • パズルだと思って、いろいろやってみよう。
# -*- coding: utf-8; -*-

# 0 から 9 までの数値をもつ配列 a がある。
a = (0..9).to_a       # => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


# 奇数の要素だけを持つ配列を作ろう
a.select{|i| i.odd?}            # => [1, 3, 5, 7, 9]


# ただし odd? メソッドは使用禁止


# 2 で割った余りが 1 なら奇数
a.select{|i| i % 2 == 1}        # => [1, 3, 5, 7, 9]


# 偶数でなければ、それは奇数
a.select{|i| !i.even?}          # => [1, 3, 5, 7, 9]


# rubyist は true/false の否定を嫌う
# reject は式が真の要素を捨て去る
a.reject{|i| i.even?}           # => [1, 3, 5, 7, 9]

## マニアが書くと
a.reject(&:even?)               # => [1, 3, 5, 7, 9]

マニアのコードに出てきた & は、スライドに登場した、ブロックの受け渡しに使う & とは少し違う。*2


演習問題 3

Enumerable#map を自作してみよう。
module Enumerable
  def my_map
    ……
  end
end
ただしEnumerable#map とEnumerable#map! は使用禁止。

会場には「mapが使えないなら collectを使えばいいじゃない」と言う人がいた。
こういうことですね。わかります。*3

module Enumerable
  def my_map &block
    collect(&block)
  end
end

a = [*0..4]             # => [0, 1, 2, 3, 4]

a.map{|i| i * 2}        # => [0, 2, 4, 6, 8]
a.my_map{|i| i * 2}     # => [0, 2, 4, 6, 8]
a.map                   # => #<Enumerator: [0, 1, 2, 3, 4]:map>
a.my_map                # => #<Enumerator: [0, 1, 2, 3, 4]:collect>

惜しい。
多くのブロック付きメソッドはブロックを渡さないと Enumerator を返す。
my_map の方は #<Enumerator: ... :collect> になっちゃってる。

# -*- coding: utf-8; -*-

# Enumerable#map を自作してみよう
# ただし Enumerable#map と Enumerable#map! は使用禁止

module Enumerable
  def my_map
    unless block_given?
      # ブロックがもらえなかったら Enumerator を返す
      to_enum __callee__
    else
      # 空の Array を用意し、
      inject([]) do |result, item|
        # ブロックの評価結果を追加する
        result << yield(item)
      end
    end
  end
end

# 試してみる
a = [*0..3]           # => [0, 1, 2, 3]

# map と my_map の比較
a.map{|i| i * 2}      # => [0, 2, 4, 6]
a.my_map{|i| i * 2}   # => [0, 2, 4, 6]

# Enumerator も比較
i = a.map             # => #<Enumerator: [0, 1, 2, 3]:map>
j = a.my_map          # => #<Enumerator: [0, 1, 2, 3]:my_map>

i.next                # => 0
i.next                # => 1
i.next                # => 2
i.next                # => 3

j.next                # => 0
j.next                # => 1
j.next                # => 2
j.next                # => 3
j.next                # => 

# ~> -:40:in `next': iteration reached an end (StopIteration)
# ~> 	from -:40:in `<main>'

詳しくは、時間がとれたら書きたい。*4

*1:There's More Than One Way To Do It. もっといいやり方があったら教えて。

*2:どう違うかはうまく説明できない。><

*3:これも反則です。

*4:コメントいただければ可能な限りお答えしたい。

2011-07-19

tweet した写真が消せなくて涙目

f:id:mas-higa:20110718172307j:image:w360

RubyKaigi2011 最終日、Heroku主催のパーティーに reject されて 30 人くらいで居酒屋へ。
しばらくすると matz が登場。写真撮影会となる。*1

翌日とある方が matz との写真について tweet していたので「私もあなたと matz の写真撮りましたよ」的な mention をしてしまった。

その後「人の顔写真晒すとかなんなの」的な展開になり写真を消すことに。

幸い fav もされてないし消せるよね …… って tweet よりも写真を消さなあかんやろ!

写真はいったいどこにポストされたのか?


lockerzって?

リンクを見ると lockerz とかいうのを使ってるらしい。

写真を消すには、たぶんログインするんだろうけど、ユーザ登録とかした覚えない。

ググッてみると元は plixi とかいうサービスだったらしい。

でも plixi もユーザ登録した覚えない。

twitter には Echofon ってアプリでアクセスしてるので、ユーザ登録も Echofon がしてくれたのか?

ログインできないので FORGOT PASSWORD? のリンクを辿ってみたけど、考えつく全てのメールアドレスを試してみても、そんなメールアドレス知らんとか言われて先に進まない。

このまま写真消せなかったら、twitter アカウント消して雲隠れするしかない。

f:id:mas-higa:20110724213859j:image:w360

ダメもとで新しいアカウントを作って twitter アカウントと連携してみたら、その新しいアカウントで写真を削除できた。

非常に焦った。

*1:私と matz の写真をお持ちの方はご連絡ください。

2011-07-16

最後の RubyKaigi に行ってきた

f:id:mas-higa:20110718173400j:image:w360

RubyKaigi 参加は今年で 2 回目。

去年は当日スタッフで参加したけど、今年は一般で参加した。*1
その代わりと言ってななんだけど、今年も個人スポンサーには応募した。

一年ぶりに Ruby 界で著名な方々にお会いした。

中には私のことを覚えてくれてる方がいて、

  • Instagram の人ですよね。
  • いつも Instagram で「いいね」ありがとうございます。

などのお言葉をいただいた。

会議の動画は vimeo.com で見られるようだ。

やっぱり RubyKaigi は刺激になる。ってか刺激が強すぎてヘコむ。


闇Ruby会議

  • 例年の Reject会議のようなもの。
  • 要 teenage spirit

「きんつばスイーツの会」としてエントリしていた @no6v さんが参加できなくなったため代打でやることになった。*2

前日の夜は半泣きでスライドを作成。

元々 @no6v さんは「参加できないかも」とか言っていたので、こうなるんじゃないかと思いつつ、何も言い出せない闇Rubyistっぷり。

ステージの上から @kakutani さん、@jugyo さんに関西Ruby会議04のオファーをしろ! と指令を受けていたのだが、なんか無駄なことを喋ってるうちに時間がなくなって、一番大切な所がグダグダになってしまった。*3

関西Ruby会議04

そんな訳で関西Ruby会議04を計画中。

関西オープンソースでは協賛企業を募集中。

詳しくは info2011(a)k-of.jp まで。

*1:もうトシなんで 3 日間立ちっぱなしとか無理。

*2:@muryoimpl さん、@spring_aki さんと一緒にステージに上がった。@morphine57 さんには裏切られた。

*3:LT 形式でオチを最後に残すなんて高度な技を要求されても……

*4:関西ではこのイベントがメイン。