Ruby いろんなループ(トリッキーなもの含む)
ループと言いつつ、やっているのは1から10の整数の乱数を作って、そこから6以上の値はもう一度やり直す。というもの
言い換えると、途中脱出が可能な無限ループ
です。え?スタックオーバーフロー?・・・
多分、最初のと最後(2018年11月24日追記分)がいいと思います。はい
puts "loopを使ったもの。多分これが一番メジャー" a = loop{ n = rand(1..10) break n if n<=5 } p a puts "再帰を使ったもの" def f n = rand(1..10) return f if n>5 n end a = f p a puts "ラムダ式を使ったもの。関数使ったやつとほぼ同じ" f = ->{ n = rand(1..10) (n<=5)? n : f.call } a = f.call p a puts "ただのwhile。他言語ならdo-whileを使う" a = nil while a.nil? || a>5 a = rand(1..10) end p a puts "whileとbreakを使ったもの" a = while true n = rand(1..10) break n if n<=5 end p a puts "例外のretryを使ったもの。速度的にも例外的にもあまり良くない気がする" a = begin n = rand(1..10) raise if n>5 n rescue retry end p a puts "いい感じのやつを自分で定義したもの" def loop1 yield end a = loop1{ n = rand(1..10) redo if n>5 n } p a puts "Integer#timesを使ったもの。" a = nil 1.times{ n = rand(1..10) if n>5 redo else a = n end } p a puts "Enumerable#mapを使ったもの。eachとかでもできるよね" a = [nil].map{ n = rand(1..10) redo if n>5 n }.first p a puts "無限リストを使ったもの。loop使ってるじゃんとか言わないで。selectで表現できるのは加点" a = Enumerator.new{|y|loop{y<<rand(1..10)}} .lazy .select{|n|n<=5} .first p a puts "関数に囲ってきれいに書けるようにしたもの" def infinite_list Enumerator.new{|y|loop{y<<yield}}.lazy end a = infinite_list{rand(1..10)} .select{|n|n<=5} .first p a # 2017年11月21日追加 puts "Rangeからの無限リスト" a = (1..Float::INFINITY) # 1/0.0で無限が作れるので、そっちでもいいのかも .lazy .map{|_|rand(1..10)} .select{|n|n<=5} .first p a puts "デフォルト引数を使ったもの" def f n=(n=rand(1..10);(n>5)? f : n) n end a = f() p a # 2018年11月24日追加 puts "loop+lazy+with_index 一年間の成長が詰まってる感じがする" a = loop .lazy .map{rand(1..10)} .select{|n|n<=5} .first p a
JavaScriptならイベントを使う方法があるらしい。
LispでDiscordBotを作る!
wispというaltJSの方言(clojureに近い)を使い、discord.jsというライブラリを使って楽をします。
discord.jsは活発なライブラリなので、新機能とかが出てきても安心ですね!
まずは、node.jsをインストール。
それぞれのライブラリをインストール
npm install discord.js
npm install wisp
そしてプログラムを入力
test.wisp
(def token "*****TOKEN*****") (def Discord (require "discord.js")) (def client (Discord.Client.)) (client.on "message" (fn [msg] (let [args (msg.content.split " ")] (console.log args) (cond (== (get args 0) "!dice") (let [num (let [n (parse-int (get args 1) 10)] (if (naN? n) 6 n))] (msg.channel.send (+ (num.->string 10) "面ダイズを振った。\nカランコロン....\n__" (+ 1 (Math.floor(* (Math.random) num))) "__"))))))) (client.login token)
(wisp初心者なので間違っているところなどありましたらコメントにお願いします ><)
(naN?問題()) (連続let・・・)
Discord側の設定や、トークンについては discordapp.com ここから
イチからDiscord Bot 。for Ruby - Qiita
Discord Bot の 簡単な作り方 – Asamac blog
ここらを適当に参考にしてください。
cat test.wisp | node_modules/.bin/wisp --no-map > test.js
すると、こんなソースコードが出力されます。
test.js
var token = exports.token = '*****TOKEN*****'; var Discord = exports.Discord = require('discord.js'); var client = exports.client = new Discord.Client(); client.on('message', function (msg) { return function () { var argsø1 = msg.content.split(' '); console.log(argsø1); return (argsø1 || 0)[0] == '!dice' ? function () { var numø1 = function () { var nø1 = parseInt((argsø1 || 0)[1], 10); return isNaN(nø1) ? 6 : nø1; }.call(this); return msg.channel.send(numø1.toString(10) + '面ダイズを振った\u3002\nカランコロン....\n__' + (1 + Math.floor(Math.random() * numø1)) + '__'); }.call(this) : void 0; }.call(this); }); client.login(token);
node test.js
あなたに快適なBOTライフを!
node v8.9.1
discord.js@11.2.1
wisp@0.10.0
メモ Ruby対数正規分布の乱数
(2017/11/16)あああタイトル間違ってましたぁ・・更新前に見た方申し訳ないです・・
合っているかは自信ないです・・
ゲームの乱数くらいにお使いください。
require "random_bell" # http://pmsl.planet.sci.kobe-u.ac.jp/~seto/?page_id=316 # をRubyに移植 def lognormal mu, sigma return Float::NAN if (mu <= 0) bell = RandomBell.new( mu: Math.log(mu*mu) - Math.log(mu*mu + sigma*sigma) / 2.0, sigma: Math.sqrt(Math.log(1 + (sigma / mu) * (sigma / mu))), range: -10..10) Math.exp(bell.rand) end
分布確認用
require"./lognormal" puts (1..10000).to_a.map{|n|lognormal(平均,分布).to_i}.inject({}){|r,n|r[n]||=0;r[n]+=1;r}.sort_by{|n,v|n}.map{|n,v|"#{n} #{"*"*v}"}
C++(標準ライブラリ)にもPython(NumPy)にもC#(Math.net)にもあるのに
Rubyにはない悲しみ
gem install random_bell
random_bellを使用しています。
random_bell (0.1.1)
ruby 2.3.3p222 (2016-11-21 revision 56859) [x64-mingw32]
Ruby 呼び出せないメソッド
define_method("!bar", ->{"foo"}) p method("!bar") p method("!bar").call # 呼び出し方 !bar #< 呼び出せない
こんなことができるとは思ってなかった
ruby 2.3.3p222 (2016-11-21 revision 56859) [x64-mingw32]
にて確認