2016年9月13日火曜日

番外編:お菓子300円問題

突然ですが…、
小学校の遠足の時「お菓子は 300 円までね~」っていうルールは無かったですか?そして、これをキッチリ使い切りたいっていう悩ましい問題に陥って駄菓子屋さんの前で長い時間を過ごしたことかと思います。ということで、今回は小学生の気持ちに戻って、「お菓子 300 円問題」を R で解決してみたいと思います。

計算自体はとても簡単です。
予め、欲しいお菓子の名前と金額を csv ファイルにまとめておき、ランダムに取り出してお小遣いから引いていきます。そして、お小遣いが0円になったら計算を終了します。もしお小遣いがマイナスになったら初めから計算し直します。


使い方 -----------------
・欲しいお菓子の名前と金額を csv ファイルを作成します。例はこちら
・以下のコードを実行し、csv ファイルを選択します。
以上

#作成日時 : 12:28 2016/09/12
#作成者名:T. Nakano
rm(list=ls())
gc();gc()

# /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

# 変数の設定 -----------------------------------------------------
# お小遣い
bgt <- 300    # 円

# データの読込み -------------------------------------------------
library(tcltk)
fileName <- tclvalue(tkgetOpenFile())
act1 <- unlist(strsplit(fileName,"/"))
act1 <- act1[-length(act1)]

directory <- NULL
if(length(act1)!=1){
for(i in 1:(length(act1)-1)){
directory <- paste(directory,act1[i],"/",sep="")
}
}
directory <- paste(directory,act1[length(act1)],sep="")
setwd(directory)
DT <- read.csv(fileName, header=T)

# 計算開始 ------------------------------------------------------
N <- round(bgt/min(DT$金額))

for(j in 1:1000){
WR <- NULL
for(i in 1:N){
elm <- round(1+runif(1)*(nrow(DT)-1))
WR <- rbind(WR, DT[elm,])
if(bgt-sum(WR$金額)<=0) break
}
if(bgt==sum(WR$金額)){
WR <- WR[order(WR$お菓子),]
write.csv(WR, file="お菓子購入リスト.csv", row.names=F)
View(WR)
break
}
}

# コメント --------------------
if(j==1000){
cat(paste(bgt,"円ちょうどになりませんでした。", "\n","「お菓子と金額.csv」を変更して再計算してください。", sep=""), "\n")
}else if(j < 1000){
cat(paste(bgt,"円ちょうどになりました。", "\n", "ファイルを保存しましたのでお菓子を買いに行きましょう。", sep=""), "\n")
}


今回は「お菓子300円問題」ということでしたが、例えば、友達とバーベキュー等をするときにも使えるかと思います。バーベキュー等のときは駄菓子と違って商品の金額のキリが悪いことがあります(牛肉876円とか)。そういうときは一の位が 1 円か 9 円のものが入っている方が計算がうまくいきますよ。