電話キーパッドの最適化


33

DvorakやNeoのような新しいキーボードレイアウトを退屈に学んでいる人々に対するこの継続的な流行は、生産性を高めていると思われるためです。キーボードレイアウトを切り替えるのは悪い考えだと思います。スピードを上げるのに数か月かかることがあり、他のコンピューターよりも最終的に5%速くなったときに、コンピューターで入力する必要がある場合はめちゃくちゃになります自分ではない。

また、これらすべての人々は、現代のコミュニケーションの本当のボトルネックがどこにあるのか、電話のキーパッドを忘れています。

これは、平均的な電話キーパッドの外観です。

電話のキーパッド

文字「r」はボタン7の3番目の文字です。したがって、携帯電話で文字「r」を入力する場合、ボタン7を3回押し、「s」の場合は4回押し、「a」の場合はボタン2を1回押します。

これを考慮すると、「d」の後に「e」を付けるのはおそらく悪い決定でした-「e」は英語のアルファベットで最も一般的に使用される文字です。したがって、「DEF」の代わりにボタン3「EDF」にラベルを付けると、キーストロークをかなり節約できます。

さらに、同じボタンを共有する2文字を入力するのは面倒であることに気付いたでしょう。「TU」を書きたい場合、「V」になるので8を3回押すだけではいけません。したがって、通常は「T」と入力し、スペースを押してからバックスペースを押し、「U」と入力します。これは、3回ではなく5回のボタンを押す操作に相当します。


TL; DR

次の2つのルールがある場合:

  • ボタンをn回押すと、文字が入力されます。nは、ボタンのラベル上の文字の位置です。
  • 同じボタンを使用して入力される2つの文字を書くには、追加の2ボタンを押す必要があります

特定のテキストが与えられた場合、ボタンを押す必要が最も少ない電話キーボードレイアウトは何ですか?ボタン2〜9のみを使用する必要があり、1と0は特別なシンボル用に予約されています。

入力

最適なレイアウトを見つける必要があるテキストは、stdinを介して提供されます。小文字のアルファベット以外のものを処理する必要はなく、入力がそれだけで構成されていると想定できます。また、入力テキストが適度に大きく、すべての文字が少なくとも一度はそこにあると想定できます(それが役立つ場合)。

出力

出力にあまり多くの制約を付けたくありません。これは、一部の言語が他の言語よりも有利になる場合があるためです。ただし、言語で配列が適切であると示されている場合は、各ラベルを改行で区切ることもできます。

最適なレイアウトは複数存在する可能性があり、それらのいずれかを印刷できます。以下に簡単な例を示します。

>> echo "jackdawslovemybigsphinxofquartz" | foo.sh
ojpt
avhz
cen
skm
dyf
wbq
ixu
lgr

ボーナスポイント

-35アルゴリズムがすべての可能なレイアウトを強引に強制していない場合(ここではHaskellの「順列」を調べています)

-3コードがテキストメッセージ(140文字)に収まり、コードを友人に送信する写真を投稿した場合。

これはStackExchangeでの最初の課題です。私はあなたがそれを好むかどうか、またはそれについて他のフィードバックがあるかどうか聞いてうれしいです!


2
CodeGolf.SEにようこそ!あなたの質問には何の問題もありませんが、メインサイトに投稿する前に、まずサンドボックスに課題を投稿してフィードバックを得たり、あいまいさを取り除いたりすることをお勧めします。
マーティンエンダー14年

ああ、それはクールだ、私は間違いなく将来的になります。
フランク14年

1
私の電話は単一の60文字のSMSを送信できますが、ブラケットを適切にサポートしていません。ボーナスはありませんか?
–ζ

1
いい質問です!誰も-35ボーナスを回避できるとは思わない。キーの2つに4文字、残りの6つに3文字のレイアウトに制限する場合でも、キーの26! / (2! * 6!) = 280,063,514,671,253,913,600,000 > 2^77単純な再配置を1回だけカウントするユニークな順列があります。
デニス14年

2
また、ソリューションのボタンを押した回数を印刷できるかどうかを尋ねます。だから、誰が最高のものを見つけたのか見てみましょう!
アントニオラガグニン14年

回答:


5

Perl、333

$_=<>;$c{$&}++while/./g;@c=sort{$c{$b}<=>$c{$a}}keys%c;$d{$&.$1}++while/.(?=(.))/g;sub f{my$x=shift;if(my$c=pop@$x){for(grep!$_[$_],0..7){my@y = @_;$y[$_]=$c;f([@$x],@y)}}else{for(0..7){$z=$_[$_];$c+=$d{$z.$_}+$d{$_.$z}for@{$a[$_]}}$c<$m?($m=$c,@n=@_):1}}while(@c){$m= ~0;f[splice@c,0,8];push@{$a[$_]},$n[$_]for 0..7}print@$_,$/for@a

ルール2向けに最適化する試みを次に示します。上記の私のコメントの後、そのルールを考慮した回答の代わりに(質問の高い評価を参照)、私はここでいくつかの努力を借りていると思いました...

ルール#2に対して最適化しないソリューションは、最適とはほど遠い出力を生成できます。長い自然な英語のテキスト(実際には「不思議の国のアリス」)、前処理(小文字のみ)、およびOJWの答えからのPerlスクリプトをチェックしました。結果は

2: ermx
3: tdfz
4: alp
5: oub
6: ick
7: nwv
8: hgj
9: syq

er 単独でそれを台無しにし、さらにいくつかの他のペアが同じキーで終了することはありませんでした...

ところで、zxqjvkbpfmygwculdrshnioateそのテキストからソートされた、頻度の高い文字です。

簡単な方法(おそらく-35ボーナスを期待)を解決し、文字を1つずつ配置し、最小のペアワイズカウントで使用可能なキーを選択しようとすると、次のようになります。

slbx
hdmz
nrf
iuj
ogv
awk
tcp
eyq

この(間違った)ソリューションのコードはここに投稿しません。たとえば、注意、cより頻繁にありw、最初に配置されます。tcct)ペアは明らかにacca)-202 + 355に対して43 + 235 よりも頻度が低くなります。しかし、その後wで終了a598 + 88 - 。私たちは、ペアで終了awし、tcそれが良いだろうが、(964の合計)actw(635の合計)。等..

そのため、次のアルゴリズムは、残りの8個(最後の場合は2個)の最も頻繁に使用される各文字を、キーパッドに既にある文字と照合し、ペアごとのカウントが最小になるように配置しようとします。

$_=<>;                          # Read STDIN.
$c{$&}++while/./g;              # Count letters (%c hash).
@c=sort{$c{$b}<=>$c{$a}}keys%c; # Sort them by frequency, ascending
$d{$&.$1}++while/.(?=(.))/g;    # (@c array), and count pairs (%d hash).

                                # Next is recursive sub that does the job.
                                # Some CPAN module for permutations
                                # would probably do better...
                                # Arguments are reference to array of what's 
                                # left un-placed of current 8-pack of letters,
sub f{                          # and 8 element list of placed letters
    my$x=shift;                 # (or undefs).
    if(my$c=pop@$x){            # Pop a letter from 8-pack (if anything left),
        for(grep!$_[$_],0..7){  # try placing it on each available key, and 
            my@y = @_;          # call sub again passing updated arguments.
            $y[$_]=$c;
            f([@$x],@y)
        }
    }else{                      # If, OTOH, 8-pack is exhausted, find sum of
        for(0..7){              # pairs count of current permutation (@_) and 
            $z=$_[$_];          # letters placed in previous rounds (8-packs).
                                # @a is "array of arrays" - note, we didn't 
                                # have to initialize it. First "8-pack" will
                                # be placed on empty keypad "automatically".
                                # We re-use undefined (i.e. 0) $c.

            $c+=$d{$z.$_}+$d{$_.$z}for@{$a[$_]}
        }
        $c<$m                   # Is sum for current placement minimal?
            ?($m=$c,@n=@_)      # Then remember this minimum and placement.
            :1
    }
}

while(@c){
    $m= ~0;                         # Initialize "minimum" with large enough 
    f[splice@c,0,8];                # number, then call sub with each 8-pack
                                    # (and empty list of placed letters 
                                    # from current round). On return,
                                    # @n will have optimal arrangement.
    push@{$a[$_]},$n[$_]for 0..7    # Then place it permanently on keypad.
}
print@$_,$/for@a                    # Show us what you've done.

結果は次のとおりです。

sdfz
hlmx
nrv
iyp
ogk
acq
twb
euj

acペアは好きではありません(結局、猫はキャラクターの1つです)が、それでもコードが間違っていなければ、それは英語にとって最適な文字配置です。正確に「ゴルフ」の努力ではなく、someい、またはそうではない、いくつかの実用的なソリューションです。


3

Python3、モンテカルロタイムです!

この問題を解決するために、最初にデフォルトのキーボードで必要な「クリック」回数をカウントします(最初はabc,def,ghi,jkl,mno,pqrs,tuv,wxyz)。次に、このキーボードを変更して、価格が安いかどうかを確認します(テキストは少ないクリックで記述されます)。このキーボードが安価な場合は、デフォルトのキーボードになります。このプロセス1M時間を繰り返します。

キーボードを変更するには、最初に変更する数を決定します(変更の最大数は、キーボードの文字の総数です)。次に、すべてのスイッチに対して、2つのボタンと2つの位置を選択し、最初の位置から2番目の位置にキャラクターを転送します。

1回あたりのスイッチの最大数は、2つの完全に異なるキーボードから切り替える必要がある変更の最小数であるため、キーボードの文字数です。(あるキーボードから他のキーボードにいつでも切り替えることができるようにしたい)

出力 echo "jackdawslovemybigsphinxofquartz" | python .\myscript.pyは次のとおりです。

61 ['anb', 'sef', 'hjc', 'iykl', 'odm', 'qgr', 'tuxv', 'wpz']

61特定のメッセージを作成するために押されたボタンの数はどこにあります。

文字(スペースおよびコメントなし):577

私はその長いことを知っていますが、私はこのものに本当に新しいです。

from random import *
S=['abc','def','ghi','jkl','mno','pqrs','tuv','wxyz']
def P(L): # perform a switch of the keys of the keyboard:to switch from a given keyboard to another, the maximum number of exchanges is the number of the keys.
    R=randint
    N = len(''.join(L))
    W = randint(1,N)   # decide how many switches to perform
    EL = list(L)
    for i in range(0,W):
        B1=R(0,len(EL)-1)   # decide what buttons are considered in the switch
        B2=R(0,len(EL)-1)
        if len(EL[B1])==0: continue   
        P1=R(0,len(EL[B1])-1)       # decide what letter to switch and where
        if len(EL[B2])==0: P2=0
        else:   P2=R(0,len(EL[B2])-1)
        C1 = EL[B1][P1]     
        EL[B1]=EL[B1].replace(C1,'')
        EL[B2]=EL[B2][:P2]+C1+EL[B2][P2:]
    return EL
def U(L,X): # count how many clicks you need to compose the text X
    S=0
    Z=' '
    for A in X:
        for T in L:
            if A in T and Z not in T: S+=1+T.index(A)
            if A in T and Z in T: S+=3+T.index(A) # if the last character was in the same button..here the penality!
        Z=A
    return S
X=input()
n_iter=10**6
L = list(S)
cc=U(L,X)
print(cc,L)
for i in range(0,n_iter): #do some montecarlo stuff
    cc=U(L,X)
    pl=P(L)
    pc=U(pl,X)
    if(cc>pc):
        L=pl 
        print(pc,L)

とてもおもしろいと思ったので、このアルゴリズムをLO HOBBITで試すことにしました(自宅にもオリジナルのコピーがあります!)。それには383964文字があり、これらは私が見つけているカップルのクリックキーパッドです:

909007 ['abc', 'def', 'ghi', 'jkl', 'mno', 'pqrs', 'tuv', 'wxyz']
879344 ['abkc', 'def', 'gqhi', 'jl', 'mno', 'rs', 'tupv', 'wxyz']
861867 ['abg', 'def', 'qhyi', 'jcl', 'mno', 'r', 'tupxv', 'swkz']
851364 ['abg', 'e', 'qchi', 'jyl', 'mn', 'dr', 'tupxv', 'sowkfz']
829451 ['ag', 'ef', 'qchi', 'jyl', 'mn', 'dbr', 'tupxv', 'sowkz']
815213 ['amg', 'ef', 'qch', 'ojyl', 'i', 'dbnr', 'tupxv', 'swkz']
805521 ['amg', 'ef', 'ch', 'ojyl', 'qi', 'dbnr', 'tupxv', 'swkz']
773046 ['amg', 'ef', 'ch', 'ojyl', 'qi', 'bnr', 'tupxv', 'dswkz']
759208 ['amg', 'eqf', 'ch', 'ojyl', 'i', 'bnr', 'tupxv', 'dswkz']
746711 ['ag', 'ekq', 'clh', 'sojy', 'bi', 'nmfr', 'tupxv', 'dwz']
743541 ['ag', 'ekq', 'clh', 'sojy', 'bi', 'nmfr', 'tpxv', 'dwuz']
743389 ['ag', 'ekq', 'clh', 'sojy', 'i', 'nmfr', 'tpxbv', 'dwuz']
734431 ['ag', 'ekq', 'lh', 'sjy', 'ci', 'nrf', 'tpxbv', 'dowumz']
705730 ['ag', 'oekq', 'lh', 'sjy', 'ci', 'nrf', 'tpxbv', 'dwumz']
691669 ['ag', 'oekq', 'lh', 'nsjy', 'ic', 'rf', 'tpxbv', 'dwumz']
665866 ['ag', 'hokq', 'el', 'nsjy', 'ic', 'rbf', 'tpxv', 'dwumz']
661610 ['agm', 'hokq', 'e', 'nsj', 'ilc', 'rbf', 'tpyxv', 'dwuz']

それで、私はこの最後のものが(クリックに関して)最も実用的なキーパッドの一つであると主張します。


最適かどうかはどうやってわかりますか?
PyRulez 14年

モンテカルロはこの方法では機能しません。最適なソリューションに近づいていくだけです。しかし、100万回の試行でソリューションが変わらない場合、おそらく最適なソリューションを使用しているとしましょう。(または、この「ローカルミニマム」から十分に動いていない)
アントニオラガニン14年

それで、挑戦のために、私たちはそれがほとんどの時間働くためにそれだけを必要としますか?
PyRulez 14年

1
@PyRulez私はこれが最適な解決策を見つけるのは簡単な問題ではないことに気づきました(可能性のあるすべての解決策を試してみる場合を除き、-35ボーナスで防ぐことを望んでいました)。
フランク14年

1
興味深い方法ですが、このタスクは正確にはそのドメインではありません。チェックして、「アリス」の場合、デフォルトのキーボードでは291613クリックが必要です。私のプログラムで最適化-195597。「モンテカルロ」アプローチでは、500万回を超える反復で207000回未満のクリックは発生しませんでした。また、文字を交換することをお勧めします。つまり、2x4 + 6x3レイアウトは一定のままです。
user2846289 14年

2

ビン2-9に最も人気のある文字を割り当てたいだけなら、Perlは127文字でそれを行うことができます...

foreach(split /\s*/,<>){$x{$_}++}
foreach(sort{$x{$b}<=>$x{$a}}keys %x){$o{$n++%8}.=$_}
for(0..7){printf "%d: %s\n",$_+2,$o{$_}}

次のようなものを与える:

echo "jackdawslovemybigsphinxofquartz" | perl ./keypad.pl
2: ajeb
3: iynz
4: suv
5: ohm
6: wkl
7: rgp
8: xfc
9: dtq

または、すべてを1行で印刷して、12文字を削除します。

foreach(split /\s*/,<>){$x{$_}++}
foreach(sort{$x{$b}<=>$x{$a}}keys %x){$o[$n++%8].=$_}
print join",",values@o,"\n";

2
あなたは簡単に100文字にこれをトリミングすることができます:$x{$_}++for split/\s*/,<>;map$o{$n++%8}.=$_,sort{$x{$b}<=>$x{$a}}keys%x;print map"$_:".$o{$_-2},2..9
ardnew

1

ハスケル、160-35 = 125

import Data.List
import GHC.Exts
main=interact f where f s=show$transpose$map($sortWith(\x->length$filter(/=x)s)['a'..'z'])[t,t.d,t.d.d,d.d.d];t=take 8;d=drop 8

例:

$ runhaskell % <<< "jackdaws loves my big sphinx of quartz"
["afpy","sgqz","ihr","ojt","bku","clv","dmw","enx"]
$ </usr/share/dict/propernames tr A-Z a-z | runhaskell % 
["atjx","edgq","rhb","nmp","iyv","lcf","ouw","skz"]

これはルール2に対して最適化されないと主張するかもしれませんが、異なるキーに最も頻繁に文字を配置します。


0

JavaScript、192-35 = 157

文字の繰り返しルールに気づいただけです。これは考慮されていません。しかし、@ mniipが彼の答えで述べたように:

これはルール2に対して最適化されないと主張するかもしれませんが、異なるキーに最も頻繁に文字を配置します。

o={}
a=[]
b=['','','','','','','','']
i=-1
s.split('').forEach(function(x){o[x]=o[x]?o[x]+1:1})
for(x in o)a.push([o[x],x])
a.sort().reverse().forEach(function(x){b[i=(i+1)%8]+=x[1]})
alert(b)

これはおそらくRubyであったでしょうが、私は家にいないので、Internet Explorer(eww)を使用せざるを得ません。でも、ゴルフからゴルフまで、ひどい言語を使うのは楽しいことです。;)

サンプル出力(入力用):

avlc,sukb,otj,irh,zqg,ypf,xne,wmd

JSにはSTDINがないため、プログラムは入力がvariableに格納されていると想定しますs


あなたにもこれを念頭において最適化されている:「同じボタンを使用して型付けされている2通の手紙を書くことは、追加の2つのボタンの押下を要求する」
デジタルトラウマ

再:最後の編集。の出力'abcdefghia'は正確には最適ではないと思います。
user2846289 14年

@VadimR「あなたはまた、入力されたテキストが合理的に大規模であり、すべての文字があると仮定することができますそこに少なくとも一回」
ドアノブ

知っている。'azbcdefghizjklmnopqzrstuvwxyz'
user2846289 14年

1
あなたは、最適化することができますb=['','','','','','','','']b=[x='',x,x,x,x,x,x,x]s.split('')s.split(x)してo[x]=o[x]?o[x]+1:1までo[x]=-~o[x]
歯ブラシ14年

0

Python(119-35 = 84):

文字列が変数aであり、小文字のみを含むと仮定します。

for h in range(8): print h+2,zip(*sorted([(__import__("collections").Counter(a)[d],d) for d in set(a)])[::-1])[1][h::8]

なし:

import collections

#a="jackdawslovemybigsphinxofquartz"
a=__import__("string").lowercase

b=collections.Counter(a)

c=set(a)

d=[(b[d],d) for d in c]

e=sorted(d)

f=e[::-1]

g=zip(*f)[1]

for h in range(8): print h+2,g[h::8]

PYG(76-35 = 41):

ああ、膨大なインポートを削除できます。繰り返しますが、これはストリップされた文字列がaにあると仮定しています。

for h in R(8): print h+2,Z(*S([(CC(a)[d],d) for d in Se(a)])[::-1])[1][h::8]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.