恭喜获得10,000个声誉!


19

@MartinBüttner赢得10,000个声誉之后,我们现在在用户页面上有3个完整的10k用户行!现在,由于我们都是程序员,因此我们希望使事情自动化,而不是手动完成。您面临的挑战是编写一个程序来自动祝贺新的1万用户。

规格

输入项

输入将是n用空格分隔的数字行。(如果您愿意,还可以使用一个逗号分隔的空格分隔数字列表,如果这样会使您的代码更短。)例如:

10 20 30 40 50
15 25 35 45 55
20 30 40 50 60

要么:

10 20 30 40 50,15 25 35 45 55,20 30 40 50 60

每个数字列表代表一天中用户的声誉值列表。

输出量

输出将是相同数量的n行(或相同长度的逗号分隔列表)。每行/列表项将是:

  • :D 如果有一个用户的信誉刚刚变得大于等于10,000。
    • :D如果有多个用户达到或超过10,000个代表计数,则用多个空格分隔。例如,:D :D :D对于3个新的10k用户。
  • :( 然后,如果输入模棱两可或不可能(请在下一节中对此进行更多说明),则停止进一步输出。
  • 如果以上两个条件都不成立,则为空。

歧义性

输入可能是不明确的。出于此挑战的目的,我们假设:

  • 信誉上限是每天200,为了挑战而忽略了接受和赏金等。
  • 用户可能不会失去声誉(再次出于简单性和挑战性考虑)。

当无法确定哪个信誉值对应于哪个用户时,输入被认为是不明确的。例如,在输入中10 20,30 40,您无法确定10代表用户成为30代表用户还是40代表用户。

如果一天中的用户不可能成为第二天的用户,则认为无法进行输入。例如,在输入中10 20,310 320,这种情况显然是不可能的,因为用户一天之内就不可能获得300个声望。用户失去声誉也是不可能的。

边缘情况

  • 初始信誉值可以从任何值开始(即,用户可以以1337信誉开始)。
  • 第一行/列表项没有输出。
  • 输入将始终在语法上有效,这意味着信誉值将始终为正整数,每行/列表项的信誉值将始终相同,依此类推。
  • 信誉值未排序;它们可以是任何顺序。

测试用例

输入:9900,10000
输出::D

输入:9900 9950 9910,10100 9950 9910,10300 10150 10110
输出::D,:D :D

输入:10 20 30,42 10 20,10 242 20,442 42 10,0 0 0,442 42 10
输出:,,,:(

输入:10 20,15 25,15 25
输出:,,

输入:9999 9998 9997,10000 9998 9997,10000 10000 9997,10300 10000 10000
输出::D,:D,:(

输入:100,90,80,70
输出::(

输入:10000 10000 10000 9999,10000 10000 10000 10000,10010 10020 10030 10040
输出::D,:(

输入:9999 9998 9997 9996,10196 10197 10198 10199,10399 10199 10197 10196
输出::D :D :D :D,


@MartinBüttner啊,没注意到。固定
门把手

该示例中的第一步也是不明确的。
马丁·恩德

1
而示例4并不是模棱两可的。
Martin Ender 2014年

(i.e. a user can start with 1337 reputation).我喜欢这是我的答复,因为... 5分钟前,直到有人赞成我的答案之一xD
Teun Pronk

示例5,步骤2也是模棱两可的(哪个10k用户是哪个?)。例7也是如此(除非您添加一些规则,以区别辨别均等用户是无关紧要的,但是,如果他后来与其他人并列,那么您如何知道第一天是哪个用户?)
Martin Ender

Answers:


12

Ruby,209个字节

编辑:我切换到Ruby,它缩短了大约30%。请参阅原始Mathematica版本的编辑历史记录。我想主要的节省是因为Ruby permutation没有忽略相同元素的切换位置(我不得不把Mathematica欺骗了)。

这使用换行符分隔的格式。

gets.split('
').map{|s|s.split.map &:to_i}.each_cons(2){|a,b|a.permutation.map{|q|q.zip(b).map{|x,y|y-x}}.reject{|d|d.any?{|x|x<0||x>200}}.size!=1?abort(':('):(puts':D '*(a.count{|d|d<1e4}-b.count{|d|d<1e4}))}

要点是这样的:

  • 获取所有连续的两天。
  • 获取前一天的所有排列,并从当日减去每个排列。
  • 放弃所有包含负或大于200的差异的结果。
  • 如果剩余排列数不是1,则输出:(
  • 否则,输出的数量将与:D新的1万名用户一样多。
  • 最后,在第一个之后的整天放下:(

少打高尔夫球:

gets.split("\n").map{|s|
  s.split.map &:to_i
}.each_cons(2){|a,b|
  a.permutation.map{|q|
    q.zip(b).map{|x,y|
      y-x
    }
  }.reject{|d|
    d.any?{|x|
      x<0||x>200
    }
  }.size!=1 ? abort(':(') : (puts ':D '*(a.count{|d|d<1e4}-b.count{|d|d<1e4}))
}

我认为这是一个美丽的枚举器链。:)

PS:是第一个对此做出答复的人,这很奇怪吗?


8
我不觉得这很奇怪。有人告诉我您拥有主场优势;)
卡尔文的爱好

因此,这将使问题中的某些示例失败,对吗?
Cruncher 2014年

@Cruncher根据规范,我认为是错误的将失败(正如我在评论中提到的那样)。如果Doorknob决定更改规格而不是固定示例,我想我将不得不对此进行重新设计。
马丁·恩德

@MartinBüttner我就是这么想的。只是确认:)
Cruncher 2014年

6

Haskell,254 249 244 232 228

import Data.List
t=m(9999<)
p(a:b:r)=(a,b,r)%(filter(all(`elem`[0..200]))$nub$m(zipWith(-)b)$permutations a)
p _=""
(a,b,r)%(_:[])=(concat$m(const":D ")$t b\\t a)++'\n':p(b:r)
_%_=":("
m=map
main=interact$p.m(m read.words).lines

一点解释:该算法与MartinBüttner所使用的算法非常相似,除了nub我花了一些心思。请注意,列表差异用于确定第n + 1天比第n:天还有10000个或更多的信誉值t b\\t a

我也同意MartinBüttner对规范的解释,并且上面的一些示例是错误的,甚至是示例2是错误的(应该是:()。


你不应该别名map吗?
自豪的haskeller 2014年

1
没错(节省2个字节),但是通过添加zinfix并替换replicate (length l) x为可以节省另外10个字节map (const x) l。Haskell很棒吗?
TheSpanishInquisition

确实是。高尔夫不错!值得注意的是,由于功能应用程序的优先级最高,因此您应该可以缩短(t b)\\(t a)t b\\t a,再输出4个字节。
骄傲的haskeller 2014年

如果有一些代码可以找到这些可以自动缩短代码的地方,那将是很好的选择。
骄傲的haskeller 2014年

您是对的@proudhaskeller,这些parethese是不必要的。谢谢。
TheSpanishInquisition
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.