nekoTheShadow’s diary

技術ブログとして始めたはずが、読書&愚痴ブログになりました(´・ω・`)

「しがない問題」を解いてみました。

お題「しがない問題」

tbpgr.hatenablog.com

@tbpgrさんが「しがない問題」というお題を作成されていたので、自分が好きなRubyとPython3、最近お勉強中のC#、そしてお仕事で最近にらめっこをすることが多いSQLで回答してみました。休日でやることがなかったので(´・ω・`) なおSQLDb2 Express-C 10.5で動作確認していますが、標準的なSQLからそれほど乖離していないと思います。

まずはRubyRubyは配列から重複なく指定された数の要素を取り出すsampleというメソッドがあるので、これを利用します。

def solve
  chars = "しくてがない".chars
  title = nil
  100.times do |n|
    title = chars.sample(4).join
    return "#{n + 1}回SIerのSEからWEB系のエンジニアに転職したが楽しくて仕方がないラジオ、略して「しがないラジオ」" if title == "しがない"
  end
  "#{title}ラジオ」ちゃうやん"
end

puts solve

お次はPython3。Python2でも動きそうな気がします(´・ω・`) Pythonにもsampleメソッドが存在するので、これを使うのが便利そうです。

import random

def solve():
    for n in range(100):
        title = "".join(random.sample("しくてがない", 4))
        if title == "しがない":
            return "第{0}回SIerのSEからWEB系のエンジニアに転職したが楽しくて仕方がないラジオ、略して「しがないラジオ」".format(n + 1)
    return "「{0}ラジオ」ちゃうやん".format(title)

if __name__ == '__main__':
    answer = solve()
    print(answer)

さてお勉強中のC#ですが、わたしのC#力が低いからか、sampleメソッドに類するものを見つけることができませんでした(´・ω・`) ただ乱数を生成するSystem.Randomクラスは用意されているので、自らsampleメソッドを実装することに。

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(solve());
    }

    static string solve()
    {
        string title = null;
        foreach(var n in Enumerable.Range(1, 100))
        {
            title = sample("しくてがない", 4);
            if (title == "しがない")
            {
                return $"第{n + 1}回SIerのSEからWEB系のエンジニアに転職したが楽しくて仕方がないラジオ、略して「しがないラジオ」";
            }
        }
        return $"「{title}ラジオ」ちゃうやん";
    }

    static Random random = new Random();

    static string sample(string chars, int len)
    {
        var idxs = new List<int>();
        while (idxs.Count < len)
        {
            var idx = random.Next(chars.Length);
            if (!idxs.Contains(idx))
            {
                idxs.Add(idx);
            }
        }
        return string.Join("", idxs.Select(idx => chars[idx]));
    }
}

最後のSQLですが……これで本当にあっているのかしらん(´・ω・`) なおSQLがいくら得意でも、実際のアプリケーション開発でこんなSQLは書いてはいけません。保守担当者が地獄を見ます(実体験)。フレームワークによる自動生成や分析屋さんが書き捨てで書く分なら問題ないのですが、メンテナビリティを考えると、シンプルなSQLがベストだと思います。

with
chars(char) as (
    select 'し' from sysibm.sysdummy1
  union
    select 'く' from sysibm.sysdummy1
  union 
    select 'て' from sysibm.sysdummy1
  union 
    select 'が' from sysibm.sysdummy1
  union 
    select 'な' from sysibm.sysdummy1
  union 
    select 'い' from sysibm.sysdummy1
),
titles(idx, title) as (
  select row_number() over (order by title), title
  from (
    select c1.char || c2.char || c3.char || c4.char as title
    from chars c1, chars c2, chars c3, chars c4  
    where c2.char not in (c1.char)
    and   c3.char not in (c1.char, c2.char)
    and   c4.char not in (c1.char, c2.char, c3.char)
  )
),
episodes(episode, idx) as (
    select 0, 0 from sysibm.sysdummy1
  union all
    select episode + 1, cast(rand() * (select count(*) from titles) as integer) + 1
    from episodes 
    where episode < 100
),
programs(episode, title) as (
  select episode, title 
  from titles t join episodes e on t.idx = e.idx
)
select case
  when (select count(*) from programs where title = 'しがない') <> 0 then
    '第' || (select min(episode) from programs where title = 'しがない') || '回SIerのSEからWEB系のエンジニアに転職したが楽しくて仕方がないラジオ、略して「しがないラジオ」'
  else
     '「' || (select title from programs where episode = 100) || 'ラジオ」ちゃうやん'
  end
from sysibm.sysdummy1

いうまでもありませんが、本問題のもとねたはTech系Podcastの「しがないラジオ」。問題の発案者である@tbpgrさん(出演もされていましたね)がTwitterでよく話題に出されていたことがきっかけで存在を知り、通勤中などに関心のある回を"拾い聴き"しています。いい視聴者じゃなくてすみません(´・ω・`)

shiganai.org

ラジオを聴いている限りだと、パーソナリティのふたりはわたしと年齢が近い感じがします。たぶんわたしのほうが1-3歳年下。またわたしも大阪出身なので、関西人には親近感を抱きがち。自分と同郷で年も近いふたりがIT業界の在り方自体に対して問題意識をもつだけではなく、実際に行動に移しているとなると、これは応援せざるを得ない。なら「全話ちゃんと聞けよ」ということなのですが――仕事が忙し杉内(2流SIer勤め並みの感想)。だれかわてに時間をおくれやす(´・ω・`)