您连续八天!


82

语言学习应用程序Duolingo有很多功能要做,但是有一个主要问题使我发疯。它告诉我我已经连续几天使用该应用程序,并显示一条消息,例如“ 您正在连续7天出现连败!”。撇开连字符和是否应拼写数字,这对大多数数字都适用,但是当您说自己连续8天出现错误时,这无疑是错误的我没有用它来学习英语,但这对于语言应用程序来说仍然是不幸的行为。

您将通过编写一个完整的程序或函数来帮助Duolingo团队,该程序或函数可以确定给定数字前应带有a还是a。一个数字前面有一个,如果它的英语口语发音与开始辅音或半元音的声音,并且在前面,如果它的发音以元音开头。因此,唯一以a开头的数字是那些以十一十八八十开头的发音。

大概Duolingo开发团队留了这个bug的原因是因为他们用光了空间,无法在应用程序中使用更多的源代码,因此您需要使此代码尽可能短,以希望他们可以将其压缩。

您的代码必须采用0到2,147,483,647之间的整数,并输出aan。尾随换行符是可选的。出于此挑战的目的,1863年被理解为1836.3,而不是163

测试用例:

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 1100 还是110 110
user3819867 2015年

11
Bilbo会不同意您的一些测试用例。:)
马丁·恩德

9
@Zaibis:这里的“ one”发音像“ wun”,具有辅音。因此,“ 一个 1001一百个连胜的一天”。
El'endia Starman 2015年

31
他们可能留下了这个错误,因为他们认为没有人会达到8天连胜纪录。
PNDA

Answers:


14

Pyth,23个字节

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

"an"通过检查第一个字母是否不是an 8以及在基数1000中考虑的数字的第一个数字既不是11也不是18,来选择要分割多少个字母。结果布尔值是要分割的字符数结束。


3
很有创意。此外,令人恐惧。
Hellreaver 2015年

29

Python 2,60个字节

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

匿名函数。添加以下n任一条件:

  • 第一位数字是8
  • 前两位数字是11或18,长度是2模3。

我知道这是一个非常老的问题,但是我认为`` n> ='8'''保存了三个字节。
林恩

@Lynn不会把九个数字弄乱吗?
xnor

哦,当然!我被测试套件愚弄了:)
林恩(Lynn)

12

GNU Sed,32岁

得分包括+1,可供-E选择。

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

在线尝试。

  • 从每个数字的末尾删除3位数字的组,直到只剩下1到3位数字
  • 匹配以8或正好11或18开头的任何数字,然后更改为 an
  • 将所有其他数字更改为 a

感谢@MartinBüttner 的视网膜方法节省了10个字节。


11

Shell + bsd游戏,30

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

从STDIN读取输入。

number将十进制字符串转换为单词。因此,确定结果是否以开始很简单e


2
为使用bsd游戏而+1,我实际上并不认为它们会有用:)
ASCIIThenANSI

@ASCIIThenANSI是的,bsd游戏在这里那里都很有用:)
Digital Trauma

9

视网膜,27字节

这与DigitalTrauma的Retina回答没有太大不同,但他们坚持要我自己张贴此内容。

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

在线尝试。

第一个正则表达式用替换所有相关的数字an,第二个正则表达式用替换所有剩余的数字a。这适用于相同的字节:

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

1
+1,这与正则测试的滥用程度几乎相同:)
2015年

1
好在,Duolingo实际上是用Retina编写的,因此将其集成起来应该很容易。还是等等,那是什么语言?
停止了逆时针转动

1
有人告诉我@ceasedtoturncounterclockwis,它实际上是用Hexagony写的,但是他们写了一个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,119113个字符

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
那讲得通。感谢您的解释。
Daniel F

1
@Pavlo很好,发现eval技巧后我忘记了单个表达式!我知道也必须有一个更好的正则表达式,但是我想不出任何更短的正则表达式。谢谢!
斯科特,

1
@Pavlo Sweet,再次更新!学习很多,非常感谢:)
Scott

2
啊!忘了刮胡子2个字节!这是最后一个:n=>/^8|^(?=1[18])..(\d{3})*$/.test(n)?'an':'a'es6fiddle.net/iiehl1ex)。它是46个字节长。
Ismael Miguel

2
@ScottKaye代码非常简单:它检查它是否以开头8,是否以开头1[18]以及数字的长度是否为2 * (3n)。基本上,这是您的整个代码,但是在一个正则表达式中。
Ismael Miguel 2015年

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总是检查前缀(八十年代八百和),但是仅当数字的位数是3加2的倍数时才检查1118十一十八)。

我们从暂定结果开始,a当找到前缀时,结果将替换为ananchorsearch用于避免从字符串中提取前缀。即使找到匹配项,我们也会继续验证其余的前缀-为什么要为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(十进制)字节,¥是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“ 843” 上是不正确的,应该是an
isaacg 2015年

@isaacg您不仅正确,而且极大地简化了我的代码。谢谢!事实证明,我只看了八,八,八,八百万个,而忽略了八千八百个这样的案例。
Sherlock15年

为什么要(-~len(n)%3)<1代替len(n)%3==2
Timwi

可以(n[:2]=="11"or n[:2]=="18")缩短到"118".contains(n[:2])
Timwi 2015年

甚至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

Japt28 27字节

'a+'npUì v ¥8ª[B18]d¥UìA³ v

在线尝试!

开箱及其工作方式

'a+'npUì v ==8||[B18]d==UìAp3  v

'a+'np  "a" + "n".repeat(...)
Uì v ==8    First digit in decimal == 8
||          or...
[B18]d      [11,18].some(...)
==UìAp3  v  == First digit in base 10**3

您可以替换1e3
Oliver '18

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

Stax,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";}

事实证明,针对8xx和8x进行显式测试的时间要比具有另一个/=10循环的时间短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/=1000i/=1e3,并且都可以&&成为&
凯文·克鲁伊森

确实确实可行:在线试用。
凯文·克鲁伊森

1
@Kevin-我曾经在那里有1e3;我在调试过程中更改了它,却忘记将其更改回原样。在&&不能全部是&,因为减法得到的整数,而不是布尔值-例如19-11是8,并且19-18是1; 看到的8 && 1是正确的,但是8 & 1是错误的。我们可以使用,&但我们需要更改-!=并添加括号。
Toby Speight,

当然啊.. &确实在这里不起作用,我不好。顺便说一句,为什么不也为您的答案添加一个TIO链接?
凯文·克鲁伊森


-1

Perl,71 55 49字节

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

我知道三元运算符会帮助一天。

让我分解一下。

  • $_=<> 接受数字作为输入。
  • $_=...模块将设置的值,$_它的使用之后。
    • ...?...:...是三元运算符。如果条件(第一个参数)为true,则返回第二个参数。否则,它返回第三个。
    • /^8/||(/^1[18]/&&length%3==2)检查数字是否以8开头或以11或18开头(1[18]接受任意一个)并且长度模3为2。
    • 如果是这样,$_请将设置为an。否则,将其设置为a
  • 然后使用来打印$_aan)的内容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

反转字符串,将其分成三部分,再次反转,然后选择适当的结尾。


5
这是错误的输入111-它让an
isaacg

你是对的。固定。
驼鹿2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.