風柳メモ

ソフトウェア・プログラミング関連の覚書が中心

一般キヨシ関数

完全に乗り遅れてしまい、いまさらそのまま書いても……と思ったけれど、より一般的な問題にしてみたらどうか、と思ってやってみた。

キヨシ関数(ズンドコキヨシ、#kiyoshi関数)とは?

qiita.com

一般キヨシ関数とは?

Object general_kiyoshi( Array phrase_pattern, String last_phrase )
第一引数
phrase_pattern
文字列の配列
例:[ "ズン", "ズン", "ズン", "ズン", "ドコ" ]
第二引数
last_phrase
最後に表示出力する文字列
例:"キ・ヨ・シ!"
戻り値 無し(void:関数内部で表示も行う場合)、もしくは、出力結果の配列、あるいは、Iterableなオブジェクト(ジェネレータ)
  1. phrase_pattern に含まれる文字列を、ランダムに出力し続ける。
    文字列の出現確率は等しくなるようにする。重複する文字列がある場合、それらは同一とみなす(上記の例の場合、"ズン"が複数個含まれるが、これらは同一とみなし、"ズン"と"ドコ"が同じ確率で出現するようにする)。
  2. phrase_pattern で指定したパターンが現れたら、last_phrase を出力し、終了する。

実装例

Python

GitHub - furyutei/general_kiyoshi: general_kiyoshi(): 一般キヨシ関数

import random
import collections

def general_kiyoshi( phrase_pattern, last_phrase ):
  phrase_pattern = collections.deque( phrase_pattern )
  phrases = list( set( phrase_pattern ) )
  current_phrase_pattern = collections.deque( [], len( phrase_pattern ) )
  
  def random_phrase_generator():
    if len( phrases ) <= 0:
      return
    
    while True:
      yield random.choice( phrases )
  
  def check_phrase_pattern():
    return ( current_phrase_pattern == phrase_pattern )
  
  for phrase in random_phrase_generator():
    yield phrase
    
    current_phrase_pattern.append( phrase )
    
    if check_phrase_pattern():
      break
  
  yield last_phrase


def kiyoshi():
  for phrase in general_kiyoshi( [ 'ズン', 'ズン', 'ズン', 'ズン', 'ドコ' ], 'キ・ヨ・シ!' ):
    print( phrase )

def cockrobin():
  for phrase in general_kiyoshi( [ 'パパンがパン', '誰が殺した', 'クックロビン', '誰が殺した', 'クックロビン' ], 'スズメが弓と矢でもって、クックロビンを殺したの' ):
    print( phrase )


kiyoshi()
# :
#ズン
#ズン
#ドコ
#ズン
#ズン
#ズン
#ズン
#ドコ
#キ・ヨ・シ!

cockrobin()
# :
#パパンがパン
#クックロビン
#誰が殺した
#誰が殺した
#誰が殺した
#誰が殺した
#パパンがパン
#パパンがパン
#クックロビン
#誰が殺した
#誰が殺した
#パパンがパン
#誰が殺した
#クックロビン
#誰が殺した
#クックロビン
#スズメが弓と矢でもって、クックロビンを殺したの
JavaScript
'use strict';

function * general_kiyoshi( phrase_pattern, last_phrase ) {
    var phrases = phrase_pattern.filter( function ( value, index, self ) {
            return ( self.indexOf( value ) === index );
        } ),
        current_phrase_pattern = new Array( phrase_pattern.length );
    
    function * random_phrase_generator() {
        if ( phrases.length <= 0 ) {
            return;
        }
        for (;;) {
            yield phrases[ Math.floor( Math.random() * phrases.length ) ];
        }
    }
    
    function check_phrase_pattern() {
        return phrase_pattern.every( function ( value, index, self ) {
            return ( current_phrase_pattern[ index ] === value );
        } );
    }
    
    for ( var phrase of random_phrase_generator() ) {
        yield phrase;
        
        current_phrase_pattern.shift();
        current_phrase_pattern.push( phrase );
        
        if ( check_phrase_pattern() ) {
            break;
        }
    }
    
    yield last_phrase;
}

function print() {
    console.log.apply( console, arguments );
}

function kiyoshi() {
    for ( var phrase of general_kiyoshi( [ 'ズン', 'ズン', 'ズン', 'ズン', 'ドコ' ], 'キ・ヨ・シ!' ) ) {
        print( phrase );
    }
}

function cockrobin() {
    for ( var phrase of general_kiyoshi( [ 'パパンがパン', '誰が殺した', 'クックロビン', '誰が殺した', 'クックロビン' ], 'スズメが弓と矢でもって、クックロビンを殺したの' ) ) {
        print( phrase );
    }
}

kiyoshi();
cockrobin();

独り言など