一時期流行した「成分解析」をPowerShellで実装してみました。
オブジェクトの生成
$analysis = New-Object PSObject
$analysis | Add-Member NoteProperty IngredientNames `
@(
"アルコール","エネルギー","おいしい水","おとぎ話",
"かさぶた","スリル","ぜい肉","みんなの願い",
"やましさ","ワガママ","哀愁","安心感","羽毛","下心",
"我慢","怪しさ","勘違い","感動","甘味料","岩石",
"奇跡","気合い","強さ","筋肉","金目の物","苦労",
"孤独","黒い計画","骨","子どもたちの夢","思いやり",
"思い出","自由","秋の味覚","出来心","女らしさ",
"消毒液","情熱","真心","清き一票","憎しみ",
"大自然の恵み","大人の秘密","誰かの犠牲","男らしさ",
"天のお告げ","天使の祝福","天然ボケ","怒り","毒物",
"鈍感力","忍耐","粘膜","農作物","美しさ","魅力",
"命の危険","優しさ","勇気","裏切り","涙"
)
$analysis | Add-Member ScriptMethod CreateRandomUniqueValues `
{
param([int]$length,[int]$max,[Random]$random)
$values = @()
while($values.Count -lt $length)
{
$value = $random.Next($max-$values.Count+1)
for($i = 0; $i -lt $values.Count; $i++)
{
if($value -ge $values[$i])
{
$value++
}
}
$values += $value
[Array]::Sort($values)
}
return $values
}
$analysis | Add-Member ScriptMethod CreateRandomDevidedValues `
{
param([int]$sourceValue, `
[int]$divisionCount,[Random]$random)
$results = @()
$rateRest = $sourceValue
for($i=0; $i -lt $divisionCount; $i++)
{
$max = $rateRest-($divisionCount-$i-1)
if($i -eq $divisionCount-1) { $rate = $rateRest }
else { $rate = $random.Next($max)+1 }
$results+=$rate
$rateRest-=$rate
}
return $results
}
$analysis | Add-Member NoteProperty ElementsMaxCount 5
$analysis | Add-Member ScriptMethod AnalyseRaw `
{
param([string]$name)
$trimedName = $name.Replace(" ","").Replace(" ","")
$random = New-Object Random $trimedName.GetHashCode()
$elementsCount = $random.Next($this.ElementsMaxCount)+1
$rates = @($this.CreateRandomDevidedValues( `
100,$elementsCount,$random))
$indices = @($this.CreateRandomUniqueValues( `
$elementsCount,$this.IngredientNames.Length-1,$random))
$results = @()
for($i=0; $i -lt $elementsCount; $i++)
{
$result = New-Object PSObject
$result | Add-Member NoteProperty Rate $rates[$i]
$result | Add-Member NoteProperty Element `
$this.IngredientNames[$indices[$i]]
$results+=$result
}
$results | Sort-Object Rate -Descending
}
$analysis | Add-Member ScriptMethod Analyse `
{
param([string]$name)
$result = @($this.AnalyseRaw($name))
if($result.Length -eq 1)
{ $format = "{0}はすべて{2}でできています。" }
else
{ $format = "{0}の{1}%は{2}でできています。" }
$this.AnalyseRaw($name) `
| %{ $format -f $name,$_.Rate,$_.Element }
}
$analysis | Add-Member NoteProperty IngredientNames `
@(
"アルコール","エネルギー","おいしい水","おとぎ話",
"かさぶた","スリル","ぜい肉","みんなの願い",
"やましさ","ワガママ","哀愁","安心感","羽毛","下心",
"我慢","怪しさ","勘違い","感動","甘味料","岩石",
"奇跡","気合い","強さ","筋肉","金目の物","苦労",
"孤独","黒い計画","骨","子どもたちの夢","思いやり",
"思い出","自由","秋の味覚","出来心","女らしさ",
"消毒液","情熱","真心","清き一票","憎しみ",
"大自然の恵み","大人の秘密","誰かの犠牲","男らしさ",
"天のお告げ","天使の祝福","天然ボケ","怒り","毒物",
"鈍感力","忍耐","粘膜","農作物","美しさ","魅力",
"命の危険","優しさ","勇気","裏切り","涙"
)
$analysis | Add-Member ScriptMethod CreateRandomUniqueValues `
{
param([int]$length,[int]$max,[Random]$random)
$values = @()
while($values.Count -lt $length)
{
$value = $random.Next($max-$values.Count+1)
for($i = 0; $i -lt $values.Count; $i++)
{
if($value -ge $values[$i])
{
$value++
}
}
$values += $value
[Array]::Sort($values)
}
return $values
}
$analysis | Add-Member ScriptMethod CreateRandomDevidedValues `
{
param([int]$sourceValue, `
[int]$divisionCount,[Random]$random)
$results = @()
$rateRest = $sourceValue
for($i=0; $i -lt $divisionCount; $i++)
{
$max = $rateRest-($divisionCount-$i-1)
if($i -eq $divisionCount-1) { $rate = $rateRest }
else { $rate = $random.Next($max)+1 }
$results+=$rate
$rateRest-=$rate
}
return $results
}
$analysis | Add-Member NoteProperty ElementsMaxCount 5
$analysis | Add-Member ScriptMethod AnalyseRaw `
{
param([string]$name)
$trimedName = $name.Replace(" ","").Replace(" ","")
$random = New-Object Random $trimedName.GetHashCode()
$elementsCount = $random.Next($this.ElementsMaxCount)+1
$rates = @($this.CreateRandomDevidedValues( `
100,$elementsCount,$random))
$indices = @($this.CreateRandomUniqueValues( `
$elementsCount,$this.IngredientNames.Length-1,$random))
$results = @()
for($i=0; $i -lt $elementsCount; $i++)
{
$result = New-Object PSObject
$result | Add-Member NoteProperty Rate $rates[$i]
$result | Add-Member NoteProperty Element `
$this.IngredientNames[$indices[$i]]
$results+=$result
}
$results | Sort-Object Rate -Descending
}
$analysis | Add-Member ScriptMethod Analyse `
{
param([string]$name)
$result = @($this.AnalyseRaw($name))
if($result.Length -eq 1)
{ $format = "{0}はすべて{2}でできています。" }
else
{ $format = "{0}の{1}%は{2}でできています。" }
$this.AnalyseRaw($name) `
| %{ $format -f $name,$_.Rate,$_.Element }
}
実行例
ちゃんと分析できています。やろうとすれば結果をある程度調整することもできますが、そのようなコードは入れていません。
PS U:\> $analysis.Analyse("谷垣禎一")
谷垣禎一の75%はやましさでできています。
谷垣禎一の17%は筋肉でできています。
谷垣禎一の6%は優しさでできています。
谷垣禎一の1%は怪しさでできています。
谷垣禎一の1%は子どもたちの夢でできています。
PS U:\>
谷垣禎一の75%はやましさでできています。
谷垣禎一の17%は筋肉でできています。
谷垣禎一の6%は優しさでできています。
谷垣禎一の1%は怪しさでできています。
谷垣禎一の1%は子どもたちの夢でできています。
PS U:\>

