challenge ケブンッリジ関数

 与えた文章の各単語の最初と最後の文字以外の文字を入れ替えた文章を出力する処理を実装して下さい。元の文章の与え方は特に問いません。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#! c:\ruby\bin\ruby.exe -Ks

class Cmabrigde
    def self.convert(word)
        cs = word.split("")
        (cs.size <= 3) ? word : cs.first + cs[1..-2].sort_by { |c| rand }.join("") + cs.last
    end
end

source = <<EOS
こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
EOS
source.each_line do |line|
    puts line.chomp.split(/\s+/).map { |word| Cmabrigde.convert(word) }.join(" ")
end

Posted feedbacks - Nested

Flatten Hidden

単語ごとにs///による置換一行でやってみました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
use strict;
use warnings;
use utf8;
use encoding "utf8", STDOUT => "cp932";

use List::Util qw/shuffle/;

sub cmabrigde
{
  my $word = shift;
  $word =~ s{
    ^(.)(.+)(.)$
  }{
    join('', $1, (split(//,$2))[shuffle 0 .. length($2)-1], $3)
  }ex;
  $word;
}

for my $line (<DATA>) {
  print join(" ", map { cmabrigde($_) } split(" ", $line)), "\n";
}

__DATA__
こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう  いぎりす  ケンブリッジ だいがく  けんきゅう  けっか
にんげん  もじ  にんしき する とき その さしいょ  さいご  もじさえ あっていれば
じゅんばん  めちゃくちゃ でも ちゃんと よめる という けんきゅう  もとづいて
わざと もじの じゅんばん  いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(define *source*
  "こんにちは みなさん おげんき ですか? わたしは げんき です。
  この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
  にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
  じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
  わざと もじの じゅんばん を いれかえて あります。
  どうです? ちゃんと よめちゃう でしょ?
  ちゃんと よめたら はんのう よろしく")

(use text.tree)
(use gauche.sequence)

(define (cmabrigde word)
  (let1 len (string-length word)
    (if (<= len 3)
      word
      (tree->string
        (list (string-ref word 0)
              (shuffle (substring word 1 (- len 1)))
              (string-ref word (- len 1)))))))

(define (cmabrigde-test)
  (print (string-join (map cmabrigde (string-split *source* #/\s+/)) " ")))

データは標準入力から受けとります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
(use gauche.sequence)

(define (cmabrigde word)
  (rxmatch-if (#/^(.)(.+)(.)$/ word) (_ h m t)
    #`",h,(shuffle m),t"
    word))

(define (main args)
  (dolist (line (port->list read-line (current-input-port)))
    (print (string-join (map cmabrigde (string-split line " "))))))
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
source.text <- "こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく"

writeLines(sapply(readLines(textConnection(source.text)), function(x){
  paste(sapply(strsplit(x, " ")[[1]], function(word){
    lt  <- strsplit(word, "")[[1]]
    len <- length(lt)
    ifelse(len<=3, word, paste(lt[c(1,sample(len-2)+1,len)], collapse=""))
  }), collapse=" ")}))
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#light

open System.Text.RegularExpressions

let cmabrigde text =
    let rand = new System.Random()
    Regex.Replace(text, @"(?<=\w)\w{2,}(?=\w)", fun (m : Match) ->
        new string(m.Value |> Seq.sort_by (ignore >> rand.Next) |> Seq.to_array))

@"こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく"
|> cmabrigde |> printfn "%s"
乱数を使っていますけど、入れ替わらない場合があってもOKなのですか?

Squeak Smalltalk で。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| source convert stream separators buffer next |

source := 'こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は イギリス の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さいしょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく。'.

convert := [:word |
    | specialChars chars |
    specialChars := 'ゃゅょっャュョッー'.
    chars := word inject: OrderedCollection new into: [:out :char |
        (specialChars includes: char)
            ifFalse: [out add: (OrderedCollection with: char)]
            ifTrue: [out last add: char].
        out].
    chars size <= 3 ifTrue: [chars concatenation as: String] ifFalse: [
        | shuffled middle |
        shuffled := (middle := chars copyFrom: 2 to: chars size - 1) shuffled.
        [shuffled = middle] whileTrue: [shuffled := middle shuffled].
        ((chars first: 1), shuffled, (chars last: 1)) concatenation as: String]].

World findATranscript: nil. Transcript clear.
stream := source readStream.
separators := Character separators, '。?'.
buffer := WriteStream on: String new.

[(next := stream next) notNil] whileTrue: [
    (separators includes: next) ifFalse: [buffer nextPut: next] ifTrue: [
        Transcript show: (convert value: buffer contents); nextPut: next.
        buffer reset]].
Transcript show: (convert value: buffer contents)

"=> こにちんは みさなん おんげき ですか? わしたは げんき です。
この ぶしょんう は イリギス の ケブンリッジ だがいく の けきゅんう の けっか
にげんん は もじ を にしんき する とき その さいしょ と さいご の もさじえ あっいてれば
じゅばんん は めくちゃちゃ でも ちゃんと よめる という けきゅんう に もづいとて
わざと もじの じゅばんん を いかれえて あまりす。
どでうす? ちゃんと よちゃめう でしょ?
ちゃんと よためら はのんう よしろく。 "

並び変えないことも並び替えることの一つと判断しました。

並び変えたり、並び替えなかったりします。

(本音を言うと、必ず違う配列になる確認がめんどかっただけ)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
using System;
using System.Collections.Generic;
using System.Text;

class Pair<S, T>
{
    public S s { get; set; }
    public T t { get; set; }
    public Pair(S s, T t) { this.s = s; this.t = t; }
    public Pair() { s = default(S); t = default(T); }
}
static class Program
{
    static Random rand = new Random();
    static void Main(string[] args)
    {
        var str = "こんにちは みなさん おげんき ですか? わたしは げんき です。\n"
                    + "この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか\n"
                    + "にんげん は もじ を にんしき する とき その さいしょ と さいご の もじさえ あっていれば\n"
                    + "じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて\n"
                    + "わざと もじの じゅんばん を いれかえて あります。\n"
                    + "どうです? ちゃんと よめちゃう でしょ?\n"
                    + "ちゃんと よめたら はんのう よろしく\n";
        Console.WriteLine(CmabridgeConvert(str));
    }
    static string CmabridgeConvert(string str)
    {
        int from = 0;
        int to = 0;
        var words = new List<Pair<string, bool>>();
        for (int i = 0; i < str.Length; i++)
        {
            if (str[i] != ' ' && str[i] != ' ' && str[i] != '\n'
                && !char.IsSymbol(str[i]) && str[i] != '?' && str[i] != '。'
                && str[i] != '、' && str[i] != '!' && str[i] != ' ' && !char.IsSeparator(str[i]))
                to++;
            else
            {
                words.Add(new Pair<string, bool>(str.Substring(from, to - from), true));
                words.Add(new Pair<string, bool>(str.Substring(to, 1), false));
                from = i + 1;
                to = i + 1;
            }
        }
        if (from != str.Length)
            words.Add(new Pair<string, bool>(str.Substring(from, to - from), true));
        var sb = new StringBuilder(str.Length);
        foreach (var word in words)
        {
            if (word.t && word.s.Length > 3)
                sb.Append(Shuffle(new StringBuilder(word.s)));
            else
                sb.Append(word.s);
        }
        return sb.ToString();
    }
    static string Shuffle(StringBuilder word)
    {
        if (word.Length == 4)
        {
            if (rand.Next(2) == 0)
            {
                char tmp = word[1];
                word[1] = word[2];
                word[2] = tmp;
            }
        }
        else
        {
            for (int i = 1; i < word.Length - 1; i++)
            {
                int j = rand.Next(1, i + 1);
                char tmp = word[i];
                word[i] = word[j];
                word[j] = tmp;
            }
        }
        return word.ToString();
    }
}
   convert ucp data
こにちんは みなさん おんげき でかす? わしたは げんき です。
この ぶんょしう は いぎりす の ケリブッンジ だいがく の けゅんきう の けっか
にげんん は もじ を にしんき する とき その さしいょ と さいご の もさじえ あっれいてば
じんばゅん は めちちゃくゃ でも ちゃんと よめる という けきんゅう に もといづて
わざと もじの じんばゅん を いれかえて あすまり。
どうです? ちゃんと よゃちめう でしょ?
ちんゃと よめたら はんのう よろしく
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Cagrdibme=:3 :';(3<#y){y;((0,(>:?~#}:}.y),_1){y)'   
convert=:3 :';>,&(<LF)@((,'' ''&;)/)(L:1)Cagrdibme(L:0)cutopen&.>cutopen y'

data=:0 :0
こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
)
qsortにランダム関数をつっこんで大丈夫なのだろうか(無限ループになったりしないかな?)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <stdio.h>
#include <stdlib.h>

#define IS_SPACE(c) ( (c) == ' ' || (c) == '\n' )
#define MBCLEN 2

/* ランダム比較関数 */
int compare_random(const void *a, const void *b) {
    return rand() - RAND_MAX / 2;
}

/* ケブンリッジ関数 */
void ciambrgde(char *buf) {
    char *p = buf;

    while (*p) {
        char *word_head;

        /* 空白を読み飛ばす */
        while (IS_SPACE(*p)) { p++; }
        if (! *p) { break; }
        /* 単語の末尾を探す */
        word_head = p;
        while (*p && ! IS_SPACE(*p)) { p += MBCLEN; }
        /* 4文字以上の単語なら入れ替えを行う */
        if ( (p - word_head) >= MBCLEN * 4 ) {
            qsort(word_head + MBCLEN, (p - word_head)/MBCLEN - 2, MBCLEN, compare_random);
        }
    }
    
    return;
}

int main() {
    char buf[] = "こんにちは みなさん おげんき ですか? わたしは げんき です。\n\
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか\n\
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば\n\
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて\n\
わざと もじの じゅんばん を いれかえて あります。\n\
どうです? ちゃんと よめちゃう でしょ?\n\
ちゃんと よめたら はんのう よろしく";
    
    ciambrgde(buf);
    printf(buf);

    return 0;
}

結構短くできた!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
source = """\
こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
"""

println source.replaceAll(/\S\S{4,}/){
    it[0] + it[1..-2].toList().sort{ Math.random() }.join() + it[-1]
}

println source.replaceAll(/(?<=\S)\S{2,}(?=\S)/){
    it.toList().sort{ Math.random() }.join()
}
し、しまた!!コピペミスです・・・

\S\S{4,}になってる・・・
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
source = """\
こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
"""

println source.replaceAll(/\S{4,}/){
    it[0] + it[1..-2].toList().sort{ Math.random() }.join() + it[-1]
}

println source.replaceAll(/(?<=\S)\S{2,}(?=\S)/){
    it.toList().sort{ Math.random() }.join()
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
文章=「こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は イギリス の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さいしょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく。」
文章を反復
    KEBUNNRIDI=""
    対象を「 」で区切って反復    
        もし、対象の文字数>3ならば
            TMP=対象を文字列分解
            START=TMP[0]
            END=TMP[TMPの配列要素数-1]
            TMPの0を配列削除
            TMPの(TMPの配列要素数-1)を配列削除
            SHUFFLE=TMP
            (SHUFFLE=TMP)の間
                TMPを配列シャッフル
            KEBUNNRIDIにSTART&(TMPを空で配列結合)&ENDを配列追加
        違えば
            KEBUNNRIDIに対象を配列追加
    KEBUNNRIDIを「 」で配列結合して表示
random.shuffle なのです
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# -*- coding: utf-8 -*-

import re
import random

source = u"""
こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
"""

def cmabridge(source):
    def shuffle_word(matched):
        word = list(matched.group(0))
        middle = word[1:-1]
        random.shuffle(middle)
        return word[0] + u"".join(middle) + word[-1]
    return re.sub(r"\S{3,}", shuffle_word, source)

print cmabridge(source)

以前http://slashdot.jp/~greentea/journal/475228で作ったものを、今回の問題に適したように改造+句読点や疑問符、改行などがちゃんと特別扱いされるようデバッグ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/python
# coding: utf-8

import sys
import random

def kambridge(s):
        strlist = s.replace('\n', '\n ').split(' ')
        li = []
        for word in [x for x in strlist]:
                if len(word) < 2:
                        li.append(word)
                        continue
                endindex = -1
                while u',.!?、。!?\n'.find(word[endindex]) != -1:
                        endindex -= 1
                chars = list(word[1:endindex])
                random.shuffle(chars)
                li.append(''.join([word[0]] + chars + list(word[endindex:])))
        return ' '.join(li).replace('\n ', '\n')

if __name__ == '__main__':
        s = u"""こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく"""

        print kambridge(s)

正規表現で「文字」の連続を単語として切り出しています(記号は1文字単位で別単語の扱いとしています)。単語が4文字以上からなる場合に最初と最後以外の文字を並び替え(順番を入替)ます。並び替えた結果、偶然、同じ単語になってしまった場合は再度並び替えるようにしています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import java.util.regex.*;
import java.util.*;

public class Sample {
    private static final Pattern SEP = Pattern.compile("(?<!\\p{L})|(?!\\p{L})");
    private static Random random = new Random();
    
    public static String shuffle(String word) {
        StringBuilder sb = new StringBuilder(word);
        while (sb.toString().equals(word)) {
            for (int i = 1; i < word.length() - 2; i++) {
                int j = random.nextInt(word.length() - i - 1) + i;
                char ci = sb.charAt(i);
                sb.setCharAt(i, sb.charAt(j));
                sb.setCharAt(j, ci);
            }
        }
        return sb.toString();
    }

    public static String cmabrigde(String source) {
        StringBuilder sb = new StringBuilder();
        for (String word : SEP.split(source)) {
            if (word.length() < 4)
                sb.append(word);
            else
                sb.append(shuffle(word));
        }
        return sb.toString();
    }
    public static void main(String[] args) {
        System.out.println(cmabrigde("こんにちは みなさん おげんき ですか? わたしは げんき です。 " +
                "この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか " +
                "にんげん は もじ を にんしき する とき その さいしょ と さいご の もじさえ あっていれば " +
                "じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて " +
                "わざと もじの じゅんばん を いれかえて あります。 " +
                "どうです? ちゃんと よめちゃう でしょ? "+
                "ちゃんと よめたら はんのう よろしく"));
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import scala.util.Sorting.stableSort

object Q249 {
  def cmabrigde(str :String) = str match {
    case _ if str.length >= 4 => str.first + suffle(str.slice(1, str.length-1)).mkString + str.last
    case _ => str
  }
  def suffle[E](seq :Seq[E]) = stableSort[E, double] (seq, {x => Math.random})
}

"""こんにちは みなさん おげんき ですか? わたしは げんき です。
   この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
   にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
   じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
   わざと もじの じゅんばん を いれかえて あります。
   どうです? ちゃんと よめちゃう でしょ?
   ちゃんと よめたら はんのう よろしく""".split("\\s+") map(Q249.cmabrigde) mkString(" ")
1
2
3
4
5
6
7
8
9
#! /usr/bin/ruby

class String
    def cambridge
        gsub (/(\b\w)(\w+)(?=\w\b)/) {$1+$2.split(//).sort_by{rand}.join}
    end
end

p 'Hello everyone, how are you doing? I am fine. This text has the had the characters permutated intentionally based on a study conducted at Cambridge University in UK, according to which a human can read documents with characters randomly permutated within each word as long as the first and the last are retained. How is it? Aren\'t you able to read this?'.cambridge

Win32版です。 Unicodeのサポートが甘いのでメモリマップドファイルで読み込んでごにょごにょやってます…入力ファイルは"wstr.txt"というUnicodeテキストファイルにあると仮定して、そのファイルの中身を処理結果で書き換えます。

順番の変え方は単純にreverse何ですが、時々順番が変わっているのに築いちゃうところもありました…「にんげん」→「にげんん」とか…英語のほうが気づきやすいかも…

出力はこちら: 「こちにんは みさなん おんげき ですか? わしたは げんき です。 この ぶょしんう は いりぎす の ケッリブンジ だがいく の けゅきんう の けっか にげんん は もじ を にしんき する とき その さいしょ と さいご の もさじえ あれいてっば じばんゅん は めちくゃちゃ でも ちんゃと よめる という けゅきんう に もいづとて わざと もじの じばんゅん を いえかれて あすまり。 どでうす? ちんゃと よゃちめう でしょ? ちんゃと よためら はのんう よしろく」

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
module Main where

import System.Win32.FileMapping
import Foreign.C.Types
import Foreign.C.String
import Foreign.Ptr
import Foreign.Marshal.Utils

cambridgeStr :: String -> String
cambridgeStr = unwords . map cambridge . words
cambridge :: String -> String
cambridge str
    | null $ drop 3 str = str
    | otherwise = (head str) : (cambridge' $ tail str)

isPunct :: Char -> Bool
isPunct ch
    | (fromEnum ch) == 0xff1f = True
    | (fromEnum ch) == 0x3020 = True
    | otherwise = False

cambridge' as = fixPunct $ reverse as

fixPunct [] = []
fixPunct (a:as)
    | isPunct a = (fixPunct as) ++ [a]
    | otherwise = as ++ [a]

cmbrInPlaceW :: Int -> Ptr CWchar -> IO ()
cmbrInPlaceW c pwzInOut = do
    (ch:str) <- peekCWStringLen (pwzInOut, c `div` 2)
    withCWString (ch:(cambridgeStr str)) (\pwzResult -> do
        copyBytes pwzInOut pwzResult (2 * (length str))    )


withMappedArea' :: (Int -> Ptr a -> IO b) -> Integer -> Integer -> MappedObject -> IO b
withMappedArea' f off c o = withMappedArea o off (fromIntegral c) (f $ fromIntegral c)

cambrFileInPlace :: String -> IO ()
cambrFileInPlace fnm =
    withMappedFile fnm True {-Write-} Nothing {- Share None-} $ withMappedArea' cmbrInPlaceW 0

main = cambrFileInPlace "wstr.txt"
バッチで。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
@echo off
  setlocal enabledelayedexpansion
    set n=0
    set s=
    set t=
    set w=
    
    if "%~1" == "" (echo usage: %~n0 FILE >&2 & exit /b 1)
    
    for /f "tokens=*" %%l in (%~1) do (
      set t=
      
      for %%w in (%%l) do (
        set w=%%w
        
        call :length !w! n
        
        if !n! gtr 3 (
          call :shuffle !w:~1,-1! s
          set t=!t!!w:~0,1!!s!!w:~-1! 
        ) else (
          set t=!t!!w! 
        )
      )
      
      echo !t!
    )
  endlocal
goto :EOF

:shuffle
  setlocal enabledelayedexpansion
    set i=0
    set j=0
    set m=0
    set n=0
    set t=
    set w=%~1
    set v=0
    
    call :length %w% n
    
    for /l %%i in (0,1,%n%) do set v[%%i]=%%i
    
    set i=0
    :L1
      set /a j=%RANDOM%%%%n%
      set v=!v[%i%]!
      set v[%i%]=!v[%j%]!
      set v[%j%]=%v%
      set /a i+=1
    if %i% lss %n% goto L1
    
    set i=0
    :L2
      set m=!v[%i%]!
      set t=%t%!w:~%m%,1!
      set /a i+=1
    if %i% lss %n% goto L2
  endlocal & set %~2=%t%
goto :EOF

:length
  setlocal enabledelayedexpansion
    set i=0
    set t=%~1
    
    if not "%t%" == "" (
      :_
        set t=!t:~1!
        set /a i+=1
      if not "!t!" == "" goto _
    )
  endlocal & set %~2=%i%
goto :EOF

メソッドを駆使してやってみました。

Collections#shuffle()が使いたかったので

#withでごちょごちょやっています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
source = """\
こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
"""

println source.readLines()*.split(/\s+/).collect{
    it.collect{ it.size() <= 3 ? it : it.toList().with{
        it.first() +                                            // 最初
        it[1..-2].with{ Collections.shuffle(it); it.join() } + // 真ん中
        it.last()                                               // 最後
    } }.join(' ')
}.join('\n')

LINQ使って素直に書くとこんなものでしょうか。

しかしLL系はさすがだなぁ・・・。この手のコード、短いこと短いこと・・・。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Program
{
    static void Main(string[] args)
    {
        var list = ケンブリッジ関数(@"こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
");
        foreach (var str in list)
            Console.WriteLine(str);
        Console.ReadLine();
    }

    static public IEnumerable<string> ケンブリッジ関数(string str)
    {
        return str.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).
            Select(elem => ケンブリッジ関数を一つづつ(elem));
    }

    static public string ケンブリッジ関数を一つづつ(string str)
    {
        Random rand = new Random();
        var elements = str.Split(new char[] { ' ', ' ' });
        var first = elements.First();
        var last = elements.Last();
        var middle = string.Join(" ", elements.Except(new List<string>() { first, last }).
            OrderBy(element => rand.NextDouble()).ToArray());
        return string.Join(" ", new string[] { first, middle, last });
    }
}

やばい、題意を取り違えた、出直してきます・・・。

でなおしました・・・orz

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Program
{
    static void Main(string[] args)
    {
        var str = ケンブリッジ関数(@"こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
");
        Console.WriteLine(str);
        Console.ReadLine();
    }

    static public string ケンブリッジ関数(string lines)
    {
        var tokenLines = lines.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).
            Select(line => ケンブリッジ関数を一行(line));
        return string.Join(Environment.NewLine, tokenLines.ToArray());
    }

    static public string ケンブリッジ関数を一行(string line)
    {
        var tokens = line.Split(new char[] { ' ' }).
            Select(token => ケンブリッジ関数を一単語(token));
        return string.Join(" ", tokens.ToArray());
    }

    static public string ケンブリッジ関数を一単語(string str)
    {
        if (str.Length <= 3) return str;
        Random rand = new Random();
        var elements = str.ToCharArray();
        var first = elements.First();
        var last = elements.Last();
        var middle = new string(elements.Except(new List<char>() { first, last }).
            OrderBy(element => rand.NextDouble()).ToArray());
        return new StringBuilder().Append(first).Append(middle).Append(last).ToString();
    }
}
おもしろそうなので、つい、つい。 アウェイ感たっぷりのOracle PL/SQLで書いてみました。 Oracle10g R2 10.2.0.4.0 for MacOSX(Intel x86-64)、データベースキャラクタセット:AL32UTF8
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
CREATE OR REPLACE FUNCTION Cambridge( iWords IN CLOB )
RETURN CLOB
IS
  words           CLOB := EMPTY_CLOB();
  word            CLOB := EMPTY_CLOB();
  nonwords        CLOB := EMPTY_CLOB();
  TYPE            t_char_table_type IS TABLE OF CHAR(1 CHAR);
  chars           t_char_table_type := t_char_table_type();
  charsInit       t_char_table_type := t_char_table_type();
  startpos        PLS_INTEGER := 1;
  endpos          PLS_INTEGER;
  l               PLS_INTEGER;
  endpos_nonwords PLS_INTEGER;
  tempwords       CLOB := EMPTY_CLOB();
  done            BOOLEAN;
  --
  FUNCTION getShuffledWord RETURN CLOB
  IS
    workCLOB CLOB := EMPTY_CLOB();
  BEGIN
    IF chars.COUNT > 0 THEN
      FOR j IN chars.FIRST..chars.LAST LOOP
        workCLOB := workCLOB || chars(j);
      END LOOP;
    END IF;
    RETURN workCLOB;
  END;
--
BEGIN
  words := iWords;
  LOOP
    endpos := REGEXP_INSTR(words, '(\s+|[[:punct:]]+|$)', startpos);
    EXIT WHEN endpos = 0;
    --
    word := DBMS_LOB.SUBSTR(words, endpos - startpos, startpos);
    chars := charsInit;
    --
    IF DBMS_LOB.getLength(word) > 3 THEN
      FOR i IN 1..DBMS_LOB.getLength(word) LOOP
        chars.EXTEND();
      END LOOP;
      chars(chars.FIRST) := DBMS_LOB.SUBSTR(word, 1, 1);
      chars(chars.LAST)  := DBMS_LOB.SUBSTR(word, 1, DBMS_LOB.getLength(word));
      --
      FOR k IN 2..DBMS_LOB.getLength(word) - 1 LOOP
          done := FALSE;
          WHILE NOT done LOOP
            l := ROUND(DBMS_RANDOM.VALUE(2, DBMS_LOB.getLength(word) - 1));
            IF chars(l) IS NULL THEN
              chars(l) := DBMS_LOB.SUBSTR(word, 1, k);
              done := TRUE;
            END IF;
          END LOOP;
      END LOOP;
      word := getShuffledWord();
    END IF;
    --
    endpos_nonwords := REGEXP_INSTR(words, '(\s+|[[:punct:]]+|$)', startpos, 1, 1);
    nonwords := DBMS_LOB.SUBSTR(words, endpos_nonwords - endpos, endpos);
    startpos := endpos + 1;
    tempwords := tempwords || word || nonwords;
  END LOOP;
  RETURN tempwords;
END;
/


SCOTT> /

ファンクションが作成されました。
SCOTT> 
SCOTT> set linesize 80
SCOTT> desc wordstable
 名前                                    NULL?    型
 ----------------------------------------- -------- ----------------------------
 ID                       NOT NULL NUMBER
 WORDS                            CLOB

SCOTT> set long 4000
SCOTT> set longchunk 400
SCOTT> select words from wordstable where id = 1;

WORDS
---------------------------------------------------------------------------
こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく


SCOTT> select cambridge(words) from wordstable where id = 1;

CAMBRIDGE(WORDS)
---------------------------------------------------------------------------
こちにんは みさなん おんげき ですか? わたしは げんき です。
この ぶょんしう は いりぎす の ケブンリッジ だいがく の けゅんきう の けっか
にげんん は もじ を にしんき する とき その さしいょ と さいご の もさじえ あてっいれば
じゅんばん は めゃくちちゃ でも ちんゃと よめる という けゅんきう に もとづいて
わざと もじの じばんゅん を いかれえて あまりす。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よためら はのんう よろしく

経過: 00:00:00.07
SCOTT>

ホントは"。"や"?"を除外して考えるべきですよね?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
$utf8_str = <<<HERE
こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
HERE;
echo Cmabrigde( $utf8_str, 'UTF-8' );

function Cmabrigde( $text, $enc )
{
    $ret = '';
    $lines = explode( "\n", $text );
    foreach ( $lines as $line ) {
        $words = explode( ' ', trim($line) );
        foreach ( $words as $word ) {
            $len = mb_strlen( $word, $enc );
            if ( 3 <  $len ) {
                $head = mb_substr( $word, 0, 1, $enc );
                $body = mb_str_shuffle( mb_substr( $word, 1, $len-2, $enc ), $enc );
                $foot = mb_substr( $word, $len-1, 1, $enc );
                $word = $head.$body.$foot;
            }
            $ret .= $word.' ';
        }
        $ret = rtrim( $ret )."\n";
    }
    return $ret;
}

function mb_str_shuffle( $str, $enc )
{
    $buff = array();
    while ( $len = mb_strlen( $str, $enc ) ) {
        $buff[] = mb_substr( $str, 0, 1, $enc );
        $str = mb_substr( $str, 1, $len, $enc);
    }
    shuffle( $buff );
    return implode( '', $buff );
}

標準入力から読みます。

% cmbr <cmbr.data

考慮した点

  • シャッフルした後は必ず元の語と異なるように
  • 句読点は除いてシャッフルするように
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
implement Cmabrigde;

include "sys.m";
    sys: Sys;
    print, sprint: import sys;
include "draw.m";
include "bufio.m";
    bufio: Bufio;
    Iobuf: import bufio;
include "rand.m";
    rand: Rand;
include "daytime.m";

Cmabrigde: module
{
    init: fn(ctxt: ref Draw->Context, argv: list of string);
};

MAXRUNE: con 16rffff;
ispunct := array[MAXRUNE] of {
    '。' => 1,
    '?' => 1,
};

init(nil: ref Draw->Context, nil: list of string)
{
    sys = load Sys Sys->PATH;
    bufio = load Bufio Bufio->PATH;
    rand = load Rand Rand->PATH;

    daytime := load Daytime Daytime->PATH;
    rand->init(daytime->now());
    task(sys->fildes(0));
}

task(fd: ref Sys->FD)
{
    fin := bufio->fopen(fd, bufio->OREAD);
    while((line := fin.gets('\n')) != nil){
        (nil, l) := sys->tokenize(line, " \t\n");
        for(p := l; p != nil; p = tl p){
            s := hd p;
            ns := len s;
            while(ispunct[s[ns-1]])
                ns--;
            if(ns >= 2)
                s = sprint("%c%s%s", s[0], shuffle(s[1:ns-1]), s[ns-1:len s]);
            print("%s ", s);
        }
        print("\n");
    }
}

shuffle(s: string): string
{
    t := s[0:];
    while(len t > 1 && t == s)
        for(i := 0; i < len t; i++){
            n := rand->rand(len t);
            c := t[i];
            t[i] = t[n];
            t[n] = c;
        }
    return t;
}

最初は、random_shuffleを使っていましたが、あまり変わらないので、 #8964を参考にreverseに変えました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <locale>
#include <string>
#include <vector>
#include <iterator>
#include <ctime>
//#include <random>
#include <pstade/oven/algorithm.hpp>
#include <pstade/oven/transformed.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/range.hpp>
namespace ov = pstade::oven;
namespace bll = boost::lambda;

//std::tr1::mt19937 mt(static_cast<unsigned int>(time(0)));

std::wstring randomize(boost::iterator_range<const wchar_t*> const& r)
{
    std::wstring s(boost::begin(r), boost::end(r));
    if (s.size() > 2)
    {
//        std::random_shuffle(s.begin() + 1, s.end() - 1, std::tr1::bind(std::tr1::uniform_int<>(), mt));
        std::reverse(s.begin() + 1, s.end() - 1);
    }
    return s;

}

int main()
{
    static const wchar_t s[] = L"こんにちは みなさん おげんき ですか ? わたしは げんき です 。 "
        L"この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか "
        L"にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば "
        L"じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて "
        L"わざと もじの じゅんばん を いれかえて あります 。 "
        L"どうです ? ちゃんと よめちゃう でしょ ? "
        L"ちゃんと よめたら はんのう よろしく";
    std::vector<boost::iterator_range<const wchar_t*>> v;
    boost::algorithm::split(v, s, bll::_1 == ' ');

    std::wcout.imbue(std::locale(""));

    ov::copy(v | ov::transformed(randomize), std::ostream_iterator<std::wstring, wchar_t>(std::wcout, L" "));
    std::wcout << std::endl;
}

今更ですが、それなりにC#3.0っぽく書いてみました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
using System;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var str = @"こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さいしょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
";
            Console.WriteLine(str.ToCambridge());
            Console.ReadKey();
        }
    }

    static class StringExtensions
    {
        static readonly Random rand = new Random();
        static public string ToCambridge(this string self)
        {
            var tokenize = from line in self.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries)
                         from token in line.Split(' ')
                           select token;

            Func<string, string> convert = x =>
            {
                if (x.Length <= 3) return x;
                var items = x.ToCharArray();
                var middle = (from c in items.Select((v, i) => new { Value = v, Index = i })
                              where c.Index != 0
                              where c.Index != items.Length - 1
                              select c.Value.ToString()).ToList();
                var shuffle = middle;
                while (shuffle.SequenceEqual(middle))
                      shuffle = middle.OrderBy(s => rand.NextDouble()).ToList();
                return items.First() + shuffle.Aggregate((l, r) => l + r) + items.Last();
            };
            return tokenize.Select(x => convert(x)).Aggregate((x, y) => x + ' ' + y);
        }
    }
}

SQL Server 2008 で確認しました。 ランダムは思いつかなかったので、先頭と末尾を除いて反転しているだけです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
WITH
  InputStr(id, str) AS (
    SELECT 1, N'こんにちは みなさん おげんき ですか ? わたしは げんき です 。 この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて わざと もじの じゅんばん を いれかえて あります 。 どうです ? ちゃんと よめちゃう でしょ ? ちゃんと よめたら はんのう よろしく '
  )
, Splitted(id, splitted_str, i, splitted_len) AS (
    SELECT
        id
      , RTRIM(SUBSTRING(str, 1, CHARINDEX(N' ', str, 1)))
      , 1
      , LEN(SUBSTRING(str, 1, CHARINDEX(N' ', str, 1))) + 1
    FROM
        InputStr
    UNION ALL
    SELECT
        Splitted.id
      , RTRIM(SUBSTRING(str, splitted_len + 1, CHARINDEX(N' ', str, splitted_len + 1) - splitted_len - 1))
      , i + 1
      , splitted_len + LEN(SUBSTRING(str, splitted_len + 1, CHARINDEX(N' ', str, splitted_len + 1) - splitted_len - 1)) + 1
    FROM
        Splitted
          INNER JOIN InputStr ON Splitted.id = InputStr.id
    WHERE
        splitted_len < LEN(str)
  )
, Cmabrigde(id, str, i) AS (
    SELECT
        id
      , CASE
        WHEN LEN(splitted_str) > 2
          THEN LEFT(splitted_str, 1)
             + REVERSE(SUBSTRING(splitted_str, 2, LEN(splitted_str) - 2))
             + RIGHT(splitted_str, 1)
          ELSE splitted_str
        END
      , i
    FROM
        Splitted
  )
, Concated(id, str, i) AS (
    SELECT
        id
      , CAST(str AS nvarchar(max))
      , 1
    FROM
      Cmabrigde
    WHERE
      i = 1
    UNION ALL
    SELECT
        Concated.id
      , CAST(Concated.str + N' ' + Cmabrigde.str AS nvarchar(max))
      , Concated.i + 1
    FROM
      Concated
        INNER JOIN Cmabrigde ON Concated.id = Cmabrigde.id
    WHERE
        Concated.i + 1 = Cmabrigde.i
  )
SELECT
    str
FROM
    Concated P
WHERE
    i = (SELECT MAX(i) FROM Concated C WHERE P.id = C.id)

alphanumericp が日本語をどう扱うかは処理系によるかもしれません。Windows 上で CLISP, SBCL では動くことを確認しました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
(defun shuffle (text from to)
  (let ((d (- to from)))
    (when (> d 1)
      (dotimes (i d)
        (rotatef (char text (+ from i))
                 (char text (+ from (random d))))))))

(defun cambridge (text)
  (loop for from = (position-if #'alphanumericp text)
                 then (or (position-if #'alphanumericp text :start to)
                          (length text))
    for to = (or (position-if-not #'alphanumericp text :start from)
                 (length text))
    while (< from (length text))
    do (shuffle text (1+ from) (1- to)))
  (write-line text))

(let ((*random-state* (make-random-state t)))
  (cambridge (copy-seq "こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく")))

alphanumericp な文字が一つもない文字列を渡したときにエラーになってました。

1
2
3
4
5
6
7
8
9
@@ -6,7 +6,7 @@
                  (char text (+ from (random d))))))))
 
 (defun cambridge (text)
-  (loop for from = (position-if #'alphanumericp text)
+  (loop for from = (or (position-if #'alphanumericp text) (return))
                  then (or (position-if #'alphanumericp text :start to)
                           (length text))
     for to = (or (position-if-not #'alphanumericp text :start from)

F#初心者です。正規表現を使いました。 わたしが投稿したC#版同様、3文字以上は必ずシャッフルされる感じになっています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#light
open System
open System.Text.RegularExpressions

let str = @"こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さいしょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく"

let rec cmabrigde (s : String) =
    let rand = new Random()
    let rec convert (s : String) = 
        let shuffle = s |> Seq.sort_by (ignore >> rand.Next) |> Seq.to_array
        if s.Length <= 1 then s.ToCharArray()
        elif s.ToCharArray() <> shuffle then shuffle else convert s 
    Regex.Replace(s, @"(?<=\w)\w{2,}(?=\w)", fun (m : Match) -> new string(m.Value |> convert))

str |> cmabrigde |> printfn "%s"
Console.ReadKey()

訂正:4文字以上ですね。失礼

最初と最後を残す方法が綺麗に書けるので、1.9で。しかしRubyは流石短い。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
def cgrabmide(txt)
  txt.each_line.map{|l|l.split.map{|wd| h, *m, l = wd.each_char.to_a;[h,m.shuffle,l].join}.join(" ")}.join($/)
end

src = <<EOS
こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
EOS

puts cgrabmide(src)

最初と最後を残す方法が綺麗に書けるので、1.9で。しかしRubyは流石短い。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
def cgrabmide(txt)
  txt.each_line.map{| l | l.split.map{|wd| h, *m, l = wd.each_char.to_a;[h,m.shuffle,l].join}.join(" ")}.join($/)
end

src = <<EOS
こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
EOS

puts cgrabmide(src)

単語末の句読点列を除いて処理するバージョン。

「どうです?」→「どですう?」と云う変換はあんまり求めているものと違う気がしたので……。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
def cgrabmide(txt)
  txt.each_line.map{|l|
    l.split.map{|wd|
      wd.gsub!(/([!?.,。、,.!?…‥]+)$/,"")
      h, *m, l = wd.each_char.to_a;[h,m.shuffle,l,$1].join
    }.join(" ")}.join($/)
end

src = <<EOS
こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく
EOS

puts cgrabmide(src)

PHP勉強中。 日本語ライブラリの利用でいろいろとはまった。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?php
print <<< END_DOC
<HTML>
<HEAD><title>Cmabrigde</title>
</HEAD><BODY>
END_DOC;

error_reporting(E_ALL);
ini_set('display_errors', 'On');
ini_set('log_errors', 'Off');

function mb_str_split($str, $length = 1) {
  if ($length < 1) return FALSE;

  $result = array();

  for ($i = 0; $i < mb_strlen($str); $i += $length) {
    $result[] = mb_substr($str, $i, $length);
  }

  return $result;
}

function Cmabrigde()
{
    $problem = split(' ',"こんにちは みなさん おげんき ですか? わたしは げんき です。 "
        ."この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか "
        ."にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば "
        ."じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて "
        ."わざと もじの じゅんばん を いれかえて あります。 "
        ."どうです? ちゃんと よめちゃう でしょ? "
        ."ちゃんと よめたら はんのう よろしく");

    foreach($problem as $word){
        $start = mb_substr($word, 0, 1);
        $end = mb_substr($word, mb_strlen($word) - 1, 1);
        $mid = mb_str_split(mb_substr($word, 1, mb_strlen($word) - 2));
        shuffle($mid);
        print $start.join("",$mid).$end." ";
    }

}

Cmabrigde();

print <<< END_DOC
</BODY>
</HTML>
END_DOC;
?>

文字が1文字の場合のバグを修正。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    foreach($problem as $word){
+        if (mb_strlen($word) > 1){
            $start = mb_substr($word, 0, 1);
            $end = mb_substr($word, mb_strlen($word) - 1, 1);
            $mid = mb_str_split(mb_substr($word, 1, mb_strlen($word) - 2));
            shuffle($mid);
            print $start.join("",$mid).$end." ";
+        }
+        else {
+            print $word;
+        }
    }
今更ですが、GHCi on Windowsで泥臭く。ソースコードはUTF-8、出力はShift_JISで。

<実行結果>
こちんには みさなん おげんき ですか? わしたは げんき です。
この ぶょんしう は いぎりす の ケッブンリジ だいがく の けきんゅう の けっか
にげんん は もじ を にしんき する とき その さしいょ と さいご の もじさえ あれ
てっいば
じばゅんん は めくちゃちゃ でも ちんゃと よめる という けきんゅう に もいとづて
わざと もじの じばんゅん を いえれかて あまりす。
どうです? ちゃんと よめちゃう でしょ?
ちんゃと よためら はのんう よしろく
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
{-# LANGUAGE ForeignFunctionInterface #-}

import List
import Random
import Foreign
import Foreign.C.String
import System.Win32.Types
import System.Win32.DLL (getModuleHandle, getProcAddress)

sample = "こんにちは みなさん おげんき ですか? わたしは げんき です。\n"
  ++ "この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか\n"
  ++ "にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば\n"
  ++ "じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて\n"
  ++ "わざと もじの じゅんばん を いれかえて あります。\n"
  ++ "どうです? ちゃんと よめちゃう でしょ?\n"
  ++ "ちゃんと よめたら はんのう よろしく"

isWordChar c = case c of
  ' '  -> False
  ' ' -> False  -- 全角スペース
  '?' -> False
  '、' -> False
  '。' -> False
  '\n' -> False
  otherwise -> True

shuffle g [] = []
shuffle g queue@(x:xs)
  | length queue <= 3 = queue
  | otherwise = x : queue' ++ [last xs]
      where b = tail $ reverse xs
            r = take (length b) (randoms g)::[Int]
            queue' = fst . unzip $ sortBy (\a b -> compare 0 $ snd a) (zip b r)

cabmrdige _ []     []     = []
cabmrdige g queue  []     = [shuffle g queue]
cabmrdige g queue (x:xs)
  | isWordChar x = cabmrdige g (queue ++ [x]) xs
  | otherwise = [shuffle g queue] ++ [[x]] ++ (cabmrdige g' [] xs)
      where g' = snd $ next g

foreign import stdcall "dynamic" pfnWideCharToMultiByte
  :: FunPtr LPVOID -> INT -> DWORD -> LPWSTR -> INT -> LPSTR -> INT -> LPSTR -> LPBOOL -> IO INT

toMBCS s =
    withCWStringLen s $ \(pchW, iLengthW) -> do
      hKernel32 <- getModuleHandle (Just "KERNEL32")
      pfn <- getProcAddress hKernel32 "WideCharToMultiByte"
      wideCharToMultiByte <- return . pfnWideCharToMultiByte $ castPtrToFunPtr pfn
      iLengthA <- wideCharToMultiByte codePage 0 pchW (toEnum iLengthW) nullPtr 0 nullPtr nullPtr
      allocaArray0 (fromEnum iLengthA) $ \chBufferA -> do
        wideCharToMultiByte codePage 0 pchW (toEnum iLengthW) chBufferA iLengthA nullPtr nullPtr
        peekCAStringLen (chBufferA, fromEnum iLengthA)
    where codePage = 932

main = do
  g <- newStdGen
  s <- toMBCS $ foldl (++) [] $ cabmrdige g [] sample
  putStrLn s

Index

Feed

Other

Link

Pathtraq

loading...