09. Typoglycemia

## 09. Typoglycemia
スペースで区切られた単語列に対して，各単語の先頭と末尾の文字は残し，それ以外の文字の順序をランダムに並び替えるプログラムを作成せよ．ただし，長さが４以下の単語は並び替えないこととする．適当な英語の文（例えば"I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."）を与え，その実行結果を確認せよ．

###Go
```go
package main

import (
	"fmt"
	"math/rand"
	"strings"
	"time"
)

/*
 *	配列からランダムで1要素を取り出し値を返す、またその配列は削除する
 */
func choice(m *[]string) string {
	//	値数内の乱数を発生
	i := rand.Intn(len(*m))

	//	該当の単語を取得しマップから削除
	str := (*m)[i]

	//	これは便利（※参考）
	*m = append((*m)[:i],(*m)[i+1:]...)

	return str
}


func main() {
	body := "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."
	var randWords []string
	fixWords := map[int]string{}	//	固定位置を残したいので位置を Map の添字にする

	//	乱数初期化
	rand.Seed(time.Now().UnixNano())

	//	単語に分割し文字数を取得
	words := strings.Split(body, " ")
	length := len(words)

	//	固定位置と可変位置の単語を分類
	for i, word := range words {
		//	先頭と末尾と4文字未満の単語は固定位置
		if i == 0 || i == (length-1) || len(word) <= 4 {
			fixWords[i] = word
		} else {
			randWords = append(randWords,word)
		}
	}

	//	単語数ループながら固定位置とか可変（乱数）位置へ単語をセット
	var result [] string
	for i:=0;i<length;i++ {
		if word, ok := fixWords[i]; ok {
			result = append(result, word)
		} else {
			result = append(result, choice(&randWords))
		}
	}

	//	結果表示
	fmt.Println(strings.Join(result, " "))
}
```


###python
```python
# -*- coding: utf-8 -*-
import random

src = "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."
fixWords = {}
randWords = []

#   単語に分割し固定位置と可変位置の単語を分類
words = src.split(" ")
for i,word in enumerate(words):
    #   先頭と末尾と4文字未満の単語は固定位置
    if i == 0 or i == (len(words)-1) or len(word) <= 4:
        fixWords[i] = word;
    else:
        randWords.append(word)

#   配列の内部をシャッフル
random.shuffle(randWords)

#   単語数ループながら固定位置とか可変（乱数）位置へ単語をセット
result = []
for i in range(len(words)):
    if i in fixWords:
        result.append(fixWords[i])
    else:
        result.append(randWords.pop(0))

#   結果を空白で結合
print ' '.join(result)
```


###Javascript
```Javascript
/*
 *	配列からランダムで1要素を取り出し値を返す、またその配列は削除する
 */
function choice() {
    //	値数内の乱数を発生し該当の単語を取得
    var i = Math.floor(Math.random() * randWords.length);
    var s = randWords[i]

    //	該当の単語を取得しマップから削除しマップを並び替え
    delete randWords[i];
    randWords = randWords.filter(function (el) { return el; }); //  削除してもマップが縮まらないので

    return s;
}


var src = "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."
var fixWords = new Map();
var randWords = [];

//	単語に分割し文字数を取得
var words = src.split(' ');

//	固定位置と可変位置の単語を分類
for (var i = 0; i < words.length; i++) {
    //	先頭と末尾と4文字未満の単語は固定位置
    if (i == 0 || i == (words.length-1) || words[i].length <= 4) {
        fixWords.set(i,words[i]);
    } else {
        randWords.push(words[i]);
    }
}


//	単語数ループながら固定位置とか可変（乱数）位置へ単語をセット
var result = []
for (var i = 0; i < words.length; i++) {
    if (fixWords.has(i)) {
        result.push(fixWords.get(i));
    }
    else {
        result.push(choice());
    }
}

console.log("Fix: ",result.join(" "));
```

## まとめ

忙しいを理由に間隔が空いてしまった。
第1章: 準備運動 がやっと終わり。これからが本番。

go の 代入if は初めて使ったが、慣れるといい感じかな。

Javascript,Python はもっと効率良く書けそう。
この2言語はもっとらしく書けそうとハマってしまうが
結局書ききれなくもとに戻るとの繰返し。

## 参考
Goのスライス要素の削除は、
@usk81 さんの [sliceからN番目の要素を削除する](https://qiita.com/usk81/items/5ff7bfe27f702d77e909) を参考


[トップ](https://qiita.com/naoshin1984/items/3d7814e2f8eb01eea8dd)