スマホの電話帳
前書き
最近、私は現代のスマートフォンのよりあいまいな使用例の1つを試していました。それは、番号で誰かに電話をかけることです。入力していると、かけようとした番号が違うのに、電話帳の一部が表示されているのに気づきました!いくつかの実験の後、私はその理由を理解しました。
それが何をするか
電話帳のすべてのエントリは、次のように調べられます。
- エントリをスペースで「単語」に分割します。
- 次のようにすべての単語を確認してください。
- 数字のすべての桁について...
- キーの現在のインデックスにある単語の文字と、現在の番号にある数字はありますか?
- そのような単語が少なくとも1つ存在する場合は、このエントリを表示します
チャレンジ
スマートフォンの動作をエミュレートします!
以下の名前のリストと数値文字列を入力として使用します。電話帳のフォーマットは自由に選択できます。電話番号が常に一致し[0-9]*、すべての名前が一致すると仮定します[0-9a-zA-Z\s]+
32〜126(両方を含む)の値を持つASCII文字で構成されるエントリを期待できます。プログラムは、任意の長さのエントリとその中の単語、および任意のサイズのリストを処理する必要があります。
フィルタリングされたリストを出力します。
入力と出力の順序は関係ありません。
次の電話キーボードを使用します。
1 | 2 | 3
| abc | def
-----------------
4 | 5 | 6
ghi | jkl | mno
-----------------
7 | 8 | 9
pqr | tuv | wxy
s | | z
-----------------
| 0 |
| |
ルール
- これはコードゴルフで、最短のコードが勝ちます
- 標準的な抜け穴はありません
電話帳、値はコンマ区切り。
noodle9, Kevin Cruijssen, Arnauld, RGS, xnor, Bubbler, J42161217, Neil, petStorm, fireflame241, Dennis, Martin Ender, Leaky Nun, Lyxal, HighlyRadioactive, Dingus, math, Beefster, Razetime, my pronoun is monicareinstate, Dom Hastings, Dion
テストケース
Input: 0815
Output: []
Input: 731
Output: []
Input: 532596
Output: []
Input: 53259
Output: [Leaky Nun]
Input: 542
Output: [J42161217]
Input: 27
Output: [Kevin Cruijssen, Arnauld]
Input: 36
Output: [Martin Ender, Dom Hastings]
Input: 6
Output; [noodle9, Neil, Martin Ender, math, my pronoun is monicareinstate, Leaky Nun]
Input: 3
Output; [Dennis, Martin Ender, fireflame241, Dingus, Dion, Dom Hastings]
```
回答
JavaScript(ES6)、102バイト
を期待します(book)(digits)。ここbookで、は文字列digitsの配列で、は整数の配列です。文字列の配列を返します。
b=>a=>b.filter(s=>eval(`/\\b[${a.map(i=>i+"01adgjmptw"[i]+"-"+"01cfilosvz"[i]).join`][`}]/i`).test(s))
オンラインでお試しください!
どうやって?
数字のシーケンスは、次の形式の正規表現に変換されます。
/\b[Dx-y][Dx-y]...[Dx-y]/i
ここDで、は元の数字であり、x-yはそれに関連付けられた文字範囲、またはD-Dfor0または1です。
たとえば、に[2,7]なり/\b[2a-c][7p-s]/iます。
電話帳を調べて、この正規表現に一致する名前のみを保持します。
コメント
b => a => // b[] = book, a[] = integer sequence
b.filter(s => // for each string s in b[]:
eval( // evaluate as JS code:
"/\\b" + // regexp delimiter, followed by \b
"[" + // followed by the first '['
a.map(i => // for each integer i in a[]:
i + // append i
"01adgjmptw"[i] // append the first range character
+ "-" + // append a '-'
"01cfilosvz"[i] // append the second range character
).join`][` + // end of map(); join with ']['
"]/i" // append the last ']' and '/i'
) // end of eval()
.test(s) // keep s if it's matching the above regular expression
) // end of filter()
Python 3、96バイト
lambda n,p:[s for s in p if' '+n in''.join([i,'%i'%min(ord(i)%32/3.2+2,9)][i>'9']for i in' '+s)]
オンラインでお試しください!
Python2でも動作します
ord(i)%32大文字と小文字の両方を範囲に変換します(1,2,3,...,24,25,26)。3.2このリストをに変換して除算し00011122233344455556667778ます。2リストに追加し、を使用minして最後の桁をに変換すると9、文字マッピングが完了し22233344455566677778889999ます。
05AB1E、34の 28 20バイト
ʒl1úA9L¦3и79ªS{‡I1úå
- @ SurculoseSputumのPython2の回答を移植して8バイトなので、彼にも必ず賛成してください!
最初の入力は連絡先のリストで、2番目は整数です。
オンラインそれを試してみたり、すべてのテストケースを確認してください。
オリジナル34の28バイトは答えます:
ʒlð¡εUεA•Ê_¢•6в<£yè«XNèå}P}à
最初の入力は連絡先のリストで、2番目は整数です。
オンラインで試してみるか(自分の名前になるテストケース、光栄です^-^)、すべてのテストケースを確認してください。
説明:
ʒ # Filter the (implicit) input-list of contacts by:
l # Convert the name to lowercase
1ú # Pad the string with a single leading space
A # Push the lowercase alphabet
9L # Push a list in the range [1,9]
¦ # Remove the first item to make the range [2,9]
3и # Repeat the list 3 times: [1,2,3,4,5,6,7,8,9,1,2,3,...,9]
79ª # Append 79 to the list: [2,3,4,5,6,7,8,9,2,3,4,...,9,79]
S # Convert the list to a flattened list of digits:
# [2,3,4,5,6,7,8,9,2,3,4,...,9,7,9]
{ # Sort the list: [2,2,2,3,3,3,...,8,8,8,9,9,9,9]
‡ # Transliterate the alphabet to these digits in the contact-string
I # Push the second input-integer
1ú # Pad it with a single leading space as well
å # And check if it's a substring of the transliterated contact-string
# (after which the filtered list of contacts is output implicitly)
ʒ # Filter the (implicit) input-list of contacts by:
l # Convert the name to lowercase
ð¡ # Split it on spaces to a list of words
# (NOTE: `#` can't be used here, because it won't result in a list for
# strings without spaces)
ε # Map each word to:
U # Pop the word and store it in variable `X`
ε # Map the digits of the (implicit) input-integer to:
A # Push the lowercase alphabet
•Ê_¢• # Push compressed integer 13101041
6в # Convert it to base-6 as list: [1,1,4,4,4,4,4,5,4,5]
< # Decrease each by 1: [0,0,3,3,3,3,3,4,3,4]
£ # Split the alphabet into parts of that size:
# ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
yè # Index the current digit into this list
« # Append the string to the current digit
X # Push the current word `X`
Nè # Index the map-index into it
å # Check if this character is in the string (i.e. "abc2" and "c" → 1)
}P # After the map: check if all digits were truthy
}à # After the map: check if this was truthy for any word
# (after which the filtered list of contacts is output implicitly)
(セクション鉱山のこの05AB1Eのヒントを参照してください?大きな整数を圧縮する方法とどのように圧縮整数リストへ?)理由を理解すること•Ê_¢•である13101041と•Ê_¢•6вされます[1,1,4,4,4,4,4,5,4,5]。
パイソン2、129の111 108バイト
lambda n,S:[s for s in S if" "+n in"".join([`(ord(c)+(c<"S")-(c>"Y"))/3-20`,c][c<"A"]for c in" "+s.upper())]
オンラインでお試しください!
電話番号の文字列と名前のリストを受け取り、一致した名前のリストを返す関数。
名前ごとに、それを同等の数字列に変換し、その名前の数字列内に電話番号が見つかった場合はその名前を返します。電話番号が名前の単語の先頭のみと一致することを確認するために、一致する前に、電話番号と名前の前にスペースが付加されます。
例:
name : "Kevin Cruijssen" -> " 53846 278457736" (notice the space at the start)
phone: "27" -> " 27"
" 27" in " 53846 278457736" -> True
R、103102バイト
編集:前にスペースがないゼロ自体は決して一致しない0 ため、連絡先名の前に (スペース)だけでなく(ゼロの後にスペース)を追加して-1バイト
function(n,l,`~`=toString)l[grepl(paste("",n),chartr(~letters,~c(7:31%/%3.13,9),paste(0,tolower(l))))]
オンラインでお試しください!
Surculose Sputumの回答と同じアプローチ:電話帳をスペースで区切られた番号に変換し、一致するものを検索します。
コメントされたコード:
find_contact=
function(n,l # n=number, l=list of contacts
,`~`=toString) # ~=alias to toString function
l[ # return all entries in the list of contacts...
grepl( # ...for which there is a match for...
paste("",n), # ...the number with prepended space...
chartr( # ...in the list made by swapping all...
~letters, # ...lowercase letters for...
~c(7:31%/%3.13,9), # ...digits from 2 to 9 in groups of 3 (or 4 for 7 and 9)...
paste("",tolower(l)) # ...in the lowercase list of contacts with prepended spaces
))]
網膜、72バイト
~(1G`
.
[$&$&-$&]
T`2-9`a\dgjm\pt\w`.-
T`2-9`cfi\l\os\vz`-.
^
Gi`(?<=\W)
オンラインでお試しください!@Arnauldの回答の別のポート。最初の行を数字とし、残りの行を電話帳とします。説明:
~(
プログラムの残りの部分を実行してから、出力をプログラムとして使用し、元の入力で実行します。
1G`
数字のある行だけを残してください。
.
[$&$&-$&]
各桁を文字クラスに変換します。
T`2-9`a\dgjm\pt\w`.-
T`2-9`cfi\l\os\vz`-.
範囲の最初と最後の文字を適切な文字に調整します。
^
Gi`(?<=\W)
Retina命令のプレフィックスを付けて、文字以外のプレフィックスが付いている場合(したがって、数字の行を除外する場合)、これらの文字に一致する行のみを保持します(大文字と小文字は区別されません)。
内部スクリプトの結果は次のようになります。
Gi`(?<=\W)[6m-o]
これは、6mno単語以外の文字の後の任意の文字に一致する行を保持するRetinaプログラムです。改行が問題の文字である場合、前の行が含まれる原因となるため、単語以外の文字を一致に含めることはできないことに注意してください。
ゼリー、26バイト
Œl>Ɱ“®K¿ʂ⁹FD»So⁸V€Ƥċ
ḲçƇ¥Ƈ
左側の名前のリストと右側の数字のリストを受け入れるダイアディックリンク。名前のリストが生成されます。
オンラインでお試しください!(フッターはリストをフォーマットします。完全なプログラムとして実行すると、暗黙的に破壊されます)
どうやって?
Œl>Ɱ“®K¿ʂ⁹FD»So⁸V€Ƥċ - Link 1: list of characters, word; list of integers, key-digits
Œl - lower-case
“®K¿ʂ⁹FD» - compressed string "AAcfilosv" ("AA"+"c"+"filos"+"v")
Ɱ - map with: [ ...mmm filos :D ]
> - greater than?
S - sum
⁸ - chain's left argument, word
o - OR (vectorises) - i.e. replace 0s with word's digit characters
Ƥ - for prefixes:
V€ - evaluate each as Jelly - i.e. cast any chars to ints
ċ - count (occurrence of key-digits) -> 1 if a prefix, else 0
ḲçƇ¥Ƈ - Main Link: list of lists of characters, names; list of integers, key-digits
Ƈ - filter keep (names) for which:
¥ - last two links as a dyad - i.e. f(name, key-digits):
Ḳ - split (name) at spaces
Ƈ - filter keep (words) for which:
ç - call last Link (1) as a dyad - i.e. g(word, key-digits)
Java 8、172バイト
C->n->C.filter(c->{var s="(?i)";for(int i:n)s+="["+"01adgjmptw".charAt(i)+"-"+"01cfilosvz".charAt(i)+i+"]";var r=0>1;for(var w:c.split(" "))r|=w.matches(s+".*");return r;})
@ArnauldのJavaScript(ES6)の回答のポートなので、彼にも必ず賛成してください!
オンラインでお試しください。
説明:
C->n-> // Method with String-Stream & Integer-array parameters and String-Stream return-type
C.filter(c->{ // Filter the input String-Stream by:
var s="(?i)"; // Create a regex-String, starting at "(?i)"
for(int i:n) // Loop over each digit of the input integer-array:
s+= // Append the following to the regex-String:
"[" // An opening square bracket
+"01adgjmptw".charAt(i)
// Appended with the `i`'th character of "01adgjmptw"
+"-" // Appended with a "-"
+"01cfilosvz".charAt(i)
// Appended with the `i`'th character of "01cfilosvz"
+i // Appended with digit `i` itself
+"]"; // Appended with a closing square bracket
var r=0>1; // Boolean `r`, starting at false
for(var w:c.split(" "))
// Split the current String by spaces, and loop over each word:
r|= // Change the boolean to true if the following is true:
w.matches( // Check if the current word regex-matches:
s // The regex-String we created earlier
+".*"); // Appended with ".*"
return r;}) // After the loop, return this boolean `r` to filter on
正規表現の説明:
String#matchesJavaのメソッドは、文字列全体に一致するように先頭^と末尾$を暗黙的に追加します。
I.e. input [5,4,2] would result in the following regex:
^(?i)[a-c2][p-s7].*$
^ $ # Match the entire string
(?i) # Match case-insensitive
[a-c # A character in the range a-c (thus in "abc")
2] # or a 2 (thus in "abc2")
[p-s # Followed by a character in the range p-s (thus in "pqrs")
7] # or a 7 (thus in "pqrs7")
.* # Followed by any amount of optional trailing characters
Pythonの3、242の 239 237バイト
def f(b,n,k=[]):
x=[[k for k in j]for j in'0 1 abc2 def3 ghi4 jkl5 mno6 pqrs7 tuv8 wxyz9'.split()]
for i in n:k=k and[p+j for p in k for j in x[i]]or x[i]
return[u for u in b if sum(j==r[:len(j)]for j in k for r in u.lower().split())]
オンラインでお試しください!
説明:数値で形成できるすべての可能なストリングを計算し、名前内の単語がそれらのストリングのいずれかで始まるかどうかを確認します。
チャコール、4342バイト
SθWS⊞υιΦυ№E⪪↥ι ⭆✂λ⁰Lθ¹⎇№ανΣE CFILOSV›νπνθ
オンラインでお試しください!リンクは、コードの詳細バージョンへのリンクです。電話帳エントリの番号と改行で終了するリストとして入力を受け取ります。編集:@JonathanAllanの数字変換アルゴリズムをコピーして1バイト節約しました。これは、p変数を再び使用できることを意味します。説明:
SθWS⊞υι
番号とエントリを入力します。(これらのバイトは、より面倒な入力形式に置き換えることで削除できます。)
υ List of phonebook entries
Φ Filtered where
ι Current entry
↥ Uppercased
⪪ Split on spaces
E Map over words
λ Current word
✂ ⁰Lθ¹ Sliced to input digits length
⭆ Map over characters and join
⎇ Ternary
α Uppercase alphabet
№ Count of (i.e. contains)
ν Current character
CFILOSV Literal string ` CFILOSV`
E Map over characters
ν Word character
› Is greater than
π Inner character
Σ Take the sum
ν Else current character
№ Count of (i.e. contains)
θ Input digits
Implicitly print
錆、158の154バイト
|a,b|b.filter(move|x|x.split(|&b|b<33).any(|w|(0..).zip(a).all(|(j,&i)|j<w.len()&&(b"@CFILOSVZ".iter().fold(1,|a,&b|a+(b<w[j]&95)as u8)==i||48+i==w[j]))))
オンラインでお試しください!
コードはの振りかけると、混乱のビットである.iter()、&とmoveあちこち。文字列は&[u8]、押された数字と同様にsとして表されます。Rustの標準ライブラリには正規表現がないため、配列から各文字の数字を手動で見つけますb"@CFILOSVZ"。大文字と小文字を区別しないのは、ビットマスキングを使用し95て実行され0x5f = 0x7f - 0x20ます。これにより、小文字が大文字に変換されます。
一部のバイトは、からb==32に切り替えb<33て(0..).zip()、の代わりにインデックスを使用することにより、編集で保存されましたw.iter().zip()。
Scala、118バイト
n=>_.filter(_ split " "exists(_.matches("(?i)"+n.map(i=>s"[$i${"01adgjmptw"(i)}-${"01cfilosvz"(i)}]").mkString+".*")))
オンラインでお試しください
@ArnauldのJavaScript(ES6)回答の移植版。
タイプのカレーラムダSeq[Int]=>Seq[String]=>Seq[String]。