あなたは8日間連続です!


82

言語学習アプリのDuolingoには多くのことがありますが、私を夢中にさせる大きな問題が1つあります。このアプリを使用した日数が7日間連続であるというメッセージが表示されますハイフネーションを省き、数字を正確に入力する必要があるかどうかは、ほとんどの数字でうまくいきますが、「8日間連続でいると言うと間違いなく間違っています!私は英語を学ぶためにそれを使用していませんが、これはまだ言語アプリにとって残念な振る舞いです。

あなたは、与えられた数がが先行されるべきかどうかを割り出し、完全なプログラムや機能書き込むことによってDuolingoチームを手助けするつもりか。番号が先行する口語英語での発音が始まる場合子音や半母音音によって、及び先行その発音は母音で始まる場合。このように先行数字のみ、その発音から始まるものであり、81118、または80

おそらくDuolingo開発チームは、アプリ内のソースコードを追加するためのスペースが足りなくなったため、このバグを残しました。したがって、このコードを圧縮できるように、このコードをできるだけ短くする必要があります。

コードは、0から2,147,483,647の整数を取り、出力aまたはである必要がありanます。末尾の改行はオプションです。この課題の目的のために、1863年は次のように読まれ一八六〇から三ではなく、1800と六十から三

テストケース:

0 → a
8 → an
11 → an
18 → an
84 → an
110 → a
843 → an
1111 → a
1863 → a
8192 → an
11000 → an
18000 → an
110000 → a
180000 → a
1141592 → a
1897932 → a
11234567 → an
18675309 → an

31
これはDuolingoによって承認されていますか?そうでない場合は、言語学習サイトで言語を改善するための費用を支払ってもらう必要があります。
Arc676

10
である1100 (AN)千百または(a)の1001百の
user3819867

11
Bilboは、テストケースの一部に同意しません。:)
マーティンエンダー

9
@Zaibis:ここで「1」は「wun」のように発音され、子音が聞こえます。したがって、「1001百の日ストリーク」。
エレンディアスターマン

31
彼らはおそらく、誰も8日間の連続記録に到達しないだろうと考えたため、このバグを残しました。
PNDA

回答:


14

Pyth、23バイト

<>n\8hz}hjsz^T3,hT18"an

これ"an"は、最初の文字がでなく、8ベース1000で考慮された場合の数字の最初の桁が11でも18でもないかどうかをチェックすることにより、末尾から切り取る文字数を選択します。結果のブール値は、スライスする文字数です終わり。


3
非常に創造的です。また、恐ろしい。
ヘルリーバー

29

Python 2、60バイト

lambda n:'a'+'n'[:`n`[0]=='8'or`n`[:2]in len(`n`)%3/2*'118']

匿名関数。次のnいずれかを追加します。

  • 最初の数字は8です
  • 最初の2桁は11または18で、長さは2モジュロ3です。

これは非常に古い質問であることは知っていますが、「n> = '8'」は3バイトを節約すると思います。
リン

@Lynnしかし、それは9を台無しにしないでしょうか?
xnor

はいもちろん!テストスイートにだまされました:)
リン

12

GNU Sed、32

スコアには-Esedのオプションの+1が含まれます。

s/^8.*|^1[18](...)*$/an/
t
ca
:

オンラインでお試しください。

  • 残りの1〜3桁になるまで、各番号の末尾から3桁のグループを削除します。
  • 8から始まる数字、または正確に11または18の数字に一致して、 an
  • 他のすべての番号を a

@MartinBüttner、10バイトを節約した網膜アプローチに感謝します。


11

シェル+ bsd-games、30

number -l|sed '/^e/{can
q};ca'

STDINから読み取った入力。

number10進数の文字列を単語に変換します。結果がで始まるかどうかを判断するのは簡単なことeです。


2
bsd-gamesを使用するための+1、私は実際にそれらがこれまでに役立つとは思わなかった:)
ASCIIThenANSI

@ASCIIThenANSIうん、BSD-ゲームが有用であり、ここそこに :)
デジタルトラウマ

9

網膜、27バイト

これはDigitalTraumaのRetinaの回答とそれほど違いはありませんが、彼らは私がこれを自分で投稿することを主張しました。

^8.*|^1[18](...)*$
an
\d+
a

オンラインでお試しください。

最初の正規表現は、関連するanすべての数値をに置き換え、2番目の正規表現は残りのすべての数値をに置き換えますa。これは同じバイトで機能します:

^8.*|^1[18](...)*$
n
^\d*
a

1
+1これは、正規性の悪用のレベルが素数性テストとほぼ同じです:)
cat

1
また、Duolingoは実際にはRetinaで記述されているため、これを統合するのは簡単です。または、それは何の言語でしたか?
反時計回りの回転を停止

1
@ceasedtoturncounterclockwis実際に六角形で書かれていると言われていますが、Retina-to-Hexagonyトランスパイラーを書いているので、これは問題になりません。
マーティンエンダー

6

C ++、101

これは私の挑戦ですので、これは競争的な答えを意味するものではありません。C ++でどれだけ短くできるかを知りたかっただけです。文字列操作は冗長すぎるため、これは数学で行われます。その状態を小さくする方法があるに違いないと思いますが、私はそれを完全に理解することはできません。

const char*f(int i){int n=0,d=0;for(;i;(!(d++%3)&(i==18|i==11))|i==8?n=1:0,i/=10);return n?"an":"a";}

4

Mathematica、53バイト

If[#~IntegerName~"Words"~StringStartsQ~"e","an","a"]&

文字列処理を使用するソリューションは、実際には長くなります。


3

PostScript、119 113文字

10 string cvs dup 0 get 56 eq exch dup length 3 mod 2 eq{0 2 getinterval dup(11)eq exch(18)eq or or}{pop}ifelse

テストコード付き:

/An
{
    10 string cvs dup 0 get 56 eq exch dup length 3 mod 2 eq{0 2 getinterval dup(11)eq exch(18)eq or or}{pop}ifelse
} def

/ShouldBeFalse [ 0 110 1111 1863 110000 180000 1141592 1897932 ] def
/ShouldBeTrue [ 8 11 18 84 843 8192 11000 18000 11234567 18675309 ] def

() = (ShouldBeFalse) = ShouldBeFalse {An =} forall
() = (ShouldBeTrue)  = ShouldBeTrue  {An =} forall

3

JavaScript(ES6)70 61 46 38バイト

n=>/^8|^1[18](...)*$/.test(n)?'an':'a'

現在のソリューションは私のオリジナルのものとは非常に異なるため、コミュニティwiki。みんな、ありがとう!

デモ:http : //www.es6fiddle.net/iio40yep/


1
それは理にかなっている。説明してくれてありがとう。
ダニエルF

1
@Pavlo非常に素晴らしい、私はevalトリックを発見した後、単一の表現を忘れていました!より良い正規表現もある必要があることは知っていましたが、それより短いものは見つけられませんでした。ありがとうございました!
スコット

1
@Pavlo Sweet、再び更新されました!たくさんの学習、ありがとうございました:)
スコット

2
早く!2バイトを剃るのを忘れた!最後がこれです:n=>/^8|^(?=1[18])..(\d{3})*$/.test(n)?'an':'a'es6fiddle.net/iiehl1ex)。長さは46バイトです。
イスマエルミゲル

2
@ScottKayeコードは非常に簡単です:それはで始まるかどうかはチェックし8、それが始まる場合、1[18]および番号の長さがある場合2 * (3n)。基本的に、これはコード全体ですが、正規表現内にあります。
イスマエルミゲル

2

真剣に、43 40バイト

9⌐9τk,;;$l3@\3*╤@\(íub)$#p'8=)XkΣ'n*'a+

ここでの戦略は10^(3n)、入力を入力よりも小さい最大値で整数で除算することにより、1、2、または3つの最上位桁のみを調べることです。

オンラインで試す

説明:

9⌐9τk,;;$l3@\3*╤@\(íub)$#p'8=)XkΣ'n*'a+
9⌐9τk                                    push [11, 18]
     ,;;                                 push 3 copies of input (n)
        $l                               get length of n as string (effectively floor(log(n,10)))
          3@\3*╤                         get largest 10^(3n) less than the length
                @\                       get most significant digits of n (x)
                  (í                     bring list from back, push the index of x in the list or -1 if not in list
                    ub)                  increment by 1, convert to boolean, shove to bottom
                       $#p               push first digit from n (as string)
                          '8=            push 1 if "8" else 0
                             )X          shove to bottom of stack, discard remaining digits
                               kΣ'n*     push sum of stack, push a string containing that many "n"s
                                    'a+  push "a", concatenate


2

Perl 6の 31の   30バイト

{'a'~'n'x?/^8|^1<[18]>[...]*$/} # 31 bytes
{<a an>[?/^8|^1<[18]>[...]*$/]} # 31 bytes
{<a an>[?/^8|^[11|18][...]*$/]} # 31 bytes

{'a'~'n'x?/^8|^1[1|8][...]*$/} # 30 bytes
{<a an>[?/^8|^1[1|8][...]*$/]} # 30 bytes

(Perl 6は[ ]非キャプチャ用の正規表現で( )使用し<[ ]>、文字セットで使用します)

使用法:

# store it in a lexical code variable for ease of use
my &code = {...}

my @a  = <0 110 1111 1863 110000 180000 1141592 1897932>;
my @an = <8 11 18 843 8192 11000 18000 11234567 18675309>;

say @a.map: &code;
say @an.map: &code;
(a a a a a a a a)
(an an an an an an an an an)

2

PostScript、109バイト

(a)exch 10 string cvs dup[exch length 3 mod 2 eq{(11)(18)}if(8)]{anchorsearch{pop pop(an)exch}if}forall pop =

コードは、番号が特定のプレフィックスで始まるかどうかを検証します。プレフィックスは8常にチェックされている(8は80代では8-数百-と)が、11181118は)桁数は3プラス2の倍数であるときにのみチェックされます。

の暫定的な結果から始めa、接頭辞が見つかると結果がに置き換えられanます。anchorsearch文字列からプレフィックスを抽出しないようにするために使用されます。一致が見つかった場合でも、残りのプレフィックスの確認を続けます。なぜ5バイトを無駄にし exitますか?–しかし、元の文字列が置き換えaられるため、誤検出が発生しないことは確かです。

オペランドスタックのa-or- an結果を出力する代わりに返すには、末尾を削除し =ます(結果の長さ:107バイト)。

テストコード:

/DO {
    ... the code above ...
} def

(Should be "a"s:)  = {0 110 1111 1863 110000 180000 1141592 1897932}     { DO } forall
(Should be "an"s:) = {8 11 18 84 843 8192 11000 18000 11234567 18675309} { DO } forall
flush

2

PostScript(バイナリトークンを使用)、63バイト

(a)’>10’¥’1’8[’>’b3’j2’={(11)(18)}if(8)]{’${’u’u(an)’>}if}’I’u=

値146(10進数)とバイト、¥165であり、$3。他のすべての印刷可能な7ビットのASCII文字であるています。

これは私のPostScript [pure ASCII]バージョンと同じですが、バイナリトークンを使用して、全体の長さを短縮します。私は3つの理由で別々に投稿します:

  • 一般的な場合、ASCIIコードを最小化する実装は、バイナリバージョンを最小化する実装と必ずしも同じではありません。ASCII PostScriptコードの一部の長い部分は、他のコードよりも圧縮率が高く、対応するバイナリバージョンは短くなります。
  • バイナリコードはどこにでも適しているわけではないため、長い場合でも、純粋なASCIIの回答が望ましい場合があります。
  • 純粋なASCII PostScript回答の長さとバイナリエンコーディングを使用した回答の長さを比較するのは公平ではありません。

1

Python 3、110 93 91 76 74 70 65 64バイト

ここに長いものがありますが、簡単なものです。

編集:isaacgのおかげで修正されました。比較後に空白を保存しました。TimwiMegobenpopAlissaのおかげで多くのバイトを節約できました。

n=input();print("a"+"n"*(len(n)%3>1and n[:2]in"118"or"8"==n[0]))

または同じバイト数の場合。

n=input();print("a"+"n"[:len(n)%3>1and n[:2]in"118"or"8"==n[0]])

ゴルフをしていない:

def a():
    n=input()
    if "8"==n[:1]:
        a = "n"
    elif len(n)%3 == 2 and (n[:2] in ["11", "18"]):
        a = "n"
    else:
        a = ""
    return "a"+a

これは、入力843「800」で正しくありませんan
isaacg

@isaacgあなたが正しいだけでなく、これは私のコードを非常に単純化します。ありがとう!80、800、800などのケースを無視しながら、私は8、8000、800万だけを見ていました。
Sherlock9

なぜ(-~len(n)%3)<1代わりにlen(n)%3==2
ティムウィ

(n[:2]=="11"or n[:2]=="18")短縮できます"118".contains(n[:2])か?
ティムウィ

それともn[:2]in"118"
ティムウィ

1

Java 10、102バイト

n->{var N=n+"";return(n>9&&"118".contains(N.substring(0,2))&N.length()%3>1)|N.charAt(0)==56?"an":"a";}

オンラインでお試しください。

説明:

n->{                  // Method with integer parameter and String return-type
  var N=n+"";         //  Input integer as String
  return(n>9&&        //  If the input has at least two digits,
    "118".contains(N.substring(0,2))
                      //  and the first two digits are "11" or "18",
    &N.length()%3>1)  //  and the length modulo-3 is 2
   |N.charAt(0)==56?  //  Or if the first digit is an '8':
     "an"             //   Return "an"
   :                  //  Else:
     "a";}            //   Return "a"


1

GNU sed -r+ BSD number、34バイト

s/(e?).*/number &/e
s//a\1/
y/e/n/

まず、英語の数値に変換します。次に、可能なイニシャル以外のすべてを削除しe、プレフィックスをa。次にe(存在する場合)をに変換しnます。ゴルフの唯一のトリックはe、最初の置換でオプションを一致させることです。そのため、次の行でパターンを再利用できます。

デモ

for i in 0 8 11 18 84 110 843 1111 1863 8192 \
    11000 18000 110000 180000 1141592 1897932 11234567 18675309
do printf "%'10d → %s\n" $i $(./66841.sed <<<$i)
done
         0 → a
         8 → an
        11 → an
        18 → an
        84 → an
       110 → a
       843 → an
     1,111 → a
     1,863 → a
     8,192 → an
    11,000 → an
    18,000 → an
   110,000 → a
   180,000 → a
 1,141,592 → a
 1,897,932 → a
11,234,567 → an
18,675,309 → an

0

TeaScript、35バイト

[18,11,8,80]I(+xh(x.n%3¶3©?'an':'a'

ここで試してみてください。

説明

               xh(x.n%3¶3           get the relevant digits from the input
                                    xh compiles to x.head which returns the
                                    first n chars of x (implicit input)
                                    ¶ ('\xb6') compiles to ||
              +                     cast the result to an integer since
                                    .includes does a strict comparison
                         ©          ('\xa9') compiles to ))
[18,11,8,80]                        array of the special cases
            I(                      I( is an alias for .includes( which
                                    returns true if the array contains the
                                    argument
                          ?'an':'a' finally, return 'an' if the array
                                    contains the number, 'a' otherwise

0

Python 2.7、66

s=`input()`
print['a','an'][s[:1]=='8'or s[:2]in len(s)%3/2*'118']

明らかに短いものではありませんlambda


0

05AB1E、26 バイト

g3%ô¬D11Qs18Q+I1£8Q+>„ans∍

おそらくもう少しゴルフすることができますが、それは機能しています。

オンラインそれを試してみたり、すべてのテストケースを確認してください

説明:

g3%                  # Length of the input, modulo-3
                     #  11234567 → 8 → 2
                     #  110000 → 6 → 0
   ô                 # Split the input into chunks of that size
                     #  11234567 and 2 → ['11', '23', '45', '67']
                     #  110000 and 0 → ['110000']
    ¬                # Take the Head (first element)
                     #  ['11', '23', '45', '67'] → '11'
                     #  ['110000'] → '110000'
     D11Q            # Does it equal 11?
                     #  '11' and 11 → 1
                     #  '110000' and 11 → 0
     s18Q            # Or does it equal 18?
                     #  '11' and 18 → 0
                     #  '110000' and 18 → 0
         +           # Add them together (if it was either 11 or 18, this becomes 1)
                     #  1 and 0 → 1
                     #  0 and 0 → 0
I1£                  # Get the first character of the input
                     #  11234567 → '1'
                     #  110000 → '1'
   8Q                # Does it equal 8?
                     #  '1' and 8 → 0
          +          # Add them together
                     #  1 and 0 → 1
                     #  0 and 0 → 0
           >         # Increase it by 1
                     #  1 → 2
                     #  0 → 1
            „ans∍    # Push "an", and shorten it to a size equal to the result above
                     #  "an" and 2 → "an"
                     #  "an" and 1 → "a"


0

スタックス、25 バイト

â-x▬♪°∞▄'δL|÷æ╪║>₧4¢ÿ·7åR

実行してデバッグする

開梱されていない、コメントされていない、これはこのように見えます。

Vk|Eh       get the first "digit" after converting to base 1000
AJ|Eh       get the first "digit" after converting to base 100
c20>9*^/    if the result is greater than 20, divide it by 10 again
"AMj"!#     is the result one of [8, 11, 18]?
^           increment by 1
.an(        keep that many characters of the string "an"

これを実行する


0

空白、243バイト

[S S S T    T   S S S S T   N
_Push_97_a][T   N
S S _Print_as_character][S S S T    N
_Push_1][S N
S _Duplicate_1][S N
S _Duplicate_1][T   N
T   T   _Read_STDIN_as_integer][T   T   T   _Retrieve_input][N
S S S T N
_Create_Label_LOOP][S N
T   _Swap_top_two][S S S T  N
_Push_1][T  S S S _Add][S N
T   _Swap_top_two][S N
S _Duplicate][S S S T   T   S S T   S S N
_Push_100][T    S S T   _Subtract][N
T   T   T   N
_If_negative_jump_to_Label_TWO_DIGITS][S S S T  S ST    S N
_Push_10][T S T S _Integer_division][N
S N
S T N
_Jump_to_Label_LOOP][N
S S T   N
_Create_Label_TWO_DIGITS][S N
S _Duplicate][S S S T   S S S N
_Push_8][T  S S T   _Subtract][N
T   S S S N
_If_zero_jump_to_Label_PRINT_n][S N
S _Duplicate][S S S T   S T T   N
_Push_11][T S S T   _Subtract][N
T   S S N
_If_0_jump_to_Label_2_MOD_3][S N
S _Duplicate][S S S T   S S T   S N
_Push_18][T S S T   _Subtract][N
T   S S N
_If_0_jump_to_Label_2_MOD_3][S S S T    S ST    S N
_Push_10][T S T S _Integer_division][S N
S _Duplicate][N
T   S N
_If_0_jump_to_Label_EXIT][N
S N
T   N
_Jump_to_Label_TWO_DIGITS][N
S S S N
_Create_Label_2_MOD_3][S N
T   _Swap_top_two][S S S T  T   N
_Push_3][T  S T T   _Modulo][S S S T    S M
_Push_2][T  S S T   _Subtract][N
T   T   N
_If_negative_jump_to_Label_EXIT][N
S S S S N
_Create_Label_PRINT_n][S S S T  T   S T T   T   S N
_Push_110_n][T  N
S S _Print_as_character][N
S S N
_Create_Label_EXIT]

強調表示としてのみ追加される文字S(スペース)、T(タブ)、およびN(改行)。
[..._some_action]説明としてのみ追加。

オンラインで試してください(未加工のスペース、タブ、改行のみ)。
プログラムがエラーで停止します:出口が見つかりません。

擬似コードの説明:

Print "a"
Integer input = STDIN as integer
Integer counter = 1
Start LOOP:
  counter = counter + 1
  If(input < 100)
    Jump to function TWO_DIGITS
  input = input integer-divided by 10
  Go to next iteration of LOOP

function TWO_DIGITS:
  If(input == 8)
    Jump to function PRINT_n
  If(input == 11 or input == 18)
    Jump to function 2_MOD_3
  input = input integer-divided by 10
  If(input == 0)
    Exit program
  Recursive call to TWO_DIGITS

function 2_MOD_3:
  If(counter modulo-3 != 2)
    Exit program
  Jump to function PRINT_n

function PRINT_n:
  Print "n"
  Exit program

0

C ++、80 79バイト

[](int i){for(;i>999;i/=1e3);return i-11&&i-18&&i/100-8&&i/10-8&&i-8?"a":"an";}

次の/=10ように、別のループを使用するよりも8xxおよび8xに対して明示的にテストする方が4バイト短いことがわかりました。

[](int i){for(;i>999;i/=1e3);for(i==11|i==18?i=8:0;i>9;i/=10);return i-8?"a":"an";}

デモ

#include <locale>
#include <cstdio>
int main(int argc, char**argv)
{
    auto const f =
        [](int i){for(;i>999;i/=1e3);return i-11&&i-18&&i/100-8&&i/10-8&&i-8?"a":"an";}
    ;

    std::locale::global(std::locale{""});
    for (int i = 1;  i < argc;  ++i) {
        auto const n = std::stoi(argv[i]);
        printf("%'10d → %s\n", n, f(n));
    }
}
         0 → a
         8 → an
        11 → an
        18 → an
        84 → an
       110 → a
       843 → an
     1,111 → a
     1,863 → a
     8,192 → an
    11,000 → an
    18,000 → an
   110,000 → a
   180,000 → a
 1,141,592 → a
 1,897,932 → a
11,234,567 → an
18,675,309 → an

私はC ++をあまりよく知りませんが、そうするi/=1000ことができi/=1e3、すべてに&&なることができます&か?
ケビンクルーッセン


1
@Kevin-ある時点で1e3がありました。デバッグ中に変更して、元に戻すのを忘れました。&&ではないすべてのことができ&減算は整数ではなくブール値を生成するので、 -例えば19-118であり、19-181です。それ8 && 1が本当であるが8 & 1、偽であることがわかります。使用できます&が、括弧に変更-!=て追加する必要があります。
トビースパイト

ああ、もちろん.. &ここではうまくいきません。ところで、なぜあなたもあなたの答えにTIOリンクを追加しませんか?
ケビンクルーイッセン


-1

Perl、71 55 49バイト

$_=<>;$_=/^8/||/^1[18]/&&length%3==1?'an':'a';say

三日演算子がいつか助けてくれることは知っていました...

これを分解してみましょう。

  • $_=<> 入力として数値を受け入れます。
  • 大きな$_=...ブロックは、$_使用後の値を設定します。
    • ...?...:...三項演算子です。条件(最初の引数)が真の場合、2番目の引数を返します。それ以外の場合は、3番目を返します。
    • /^8/||(/^1[18]/&&length%3==2)番号が8で始まるか、11または18で始まる(1[18]いずれかを受け入れる)かどうかを確認し、長さmod 3が2です。
    • その場合$_は、に設定されanます。それ以外の場合は、に設定されaます。
  • 次に、$_aまたはan)の内容をで出力しsayます。

変更点

  • msh210のおかげで16バイト節約されました。
  • 括弧を削除し、デフォルトを使用して、6バイトを節約しました。

$_=<>;$_=(/^8/)||/^1[18]/&&length($_)%3==1?'an':'a';say数バイト節約します。(比較する数値は改行文字によって異なりますが、バイト数は変わりません。)
msh210

@ msh210わずか55バイトのように見えますが、これは16バイトを節約することを意味します。それを追加します。ありがとう!
ASCIIThenANSI

どういたしまして。ああ、あなたは最初の括弧を落とすことができます(私は推測します。私はテストしていません)。私はあなたも変更length($_)することができると思いますlength(または少なくとも括弧をドロップします)が、それは何らかの理由で私のために働いていません。
msh210

@ msh210はい、かっこをドロップし($_)て取得することができますが$_=<>;$_=/^8/||/^1[18]/&&length%3==1?'an':'a';say、これはたった49バイトです。
ASCIIThenANSI

あなたは、使用していくつかのバイトを保存することができます-p代わりに$_=<>してsayy///c代わりにlength、と周りの引用符をドロップするaanperl -pe'$_=/^8/||/^1[18]/&&y///c%3==2?an:a'(のために34バイト+ 1 -p)。入力は改行で終わらないことに注意してくださいecho -n 11 | perl -pe'...'。これはバグも修正します:length%3==2はとしてlength(%3)==2ではなくとして解析されるlength($_)%3==2ため、常にfalseを返します。
ThisSuitIsBlackNot

-1

ピス、29 31

?:_ec_z3"(^18$|^11$|^8)"0"an"\a

文字列を反転し、3つのセクションに分割し、再度反転して、適切なエンディングを選択します。


5
これは、入力時に間違っている111-それは与えan
isaacg

あなたが正しい。一定。
ムース
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.