做出最大和最小的数字


13

这篇帖子的灵感来自于Puzzling。这个难题的破坏者在下面。

给定三个正整数作为输入,(x, y, z)构造包含范围[x, y],将该范围连接在一起,然后删除z不必要的连续数字以产生可能的最大和最小正整数。不允许前导零(即,数字必须以开头[1-9])。以任意顺序输出这两个数字。

对于Puzzling帖子中的示例,对于input (1, 100, 100),最大可能的数字是99999785960616263646566676869707172737475767778798081828384858687888990919293949596979899100
而最小的数字是10000012340616263646566676869707172737475767778798081828384858687888990919293949596979899100
遵循jafe在此处发布答案的以下逻辑:

  • 我们不能影响数字的长度(有固定的数字位数),因此要使值最大化,我们采用最大的第一位数字,然后选择第二位数字等。
  • 删除84个第一个非昵称(要删除的剩余16位数字): 999995051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  • 接下来的17位数字中最大的数字是7,因此从此处开始,答案中的第二位数字最多为7(我们不能删除超过16位的数字)。因此,删除15个非7的...(剩下1个数字以删除):999997585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  • 从这里开始,下一位数字最多为8,因此从中间去除一个非8的数字: 99999785960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  • 逻辑类似,但取反(即,我们希望前导1s而不是前导9s)的最小数字。

这是一个较小的示例:(1, 10, 5)

我们构造范围12345678910并确定5可以删除的位数,以保留最大可能的数字。显然,这意味着我们要最大化前导位数,因为我们不能影响输出的长度。因此,如果我们删除12345,我们将剩下678910,这就是我们可以做的最大的事情。最小化是有点棘手的,因为我们可以取中间的数字,而123410尽可能保留最小。

对于(20, 25, 11),结果相当无聊,因为51

最后,排除答案试图前导零,(9, 11, 3)使91011这反过来产量9110作为最大和最小的。

I / O和规则

  • 如果更容易/更短,您可以编写两个程序/函数-一个用于最大的程序,或者一个用于最小的程序-在这种情况下,您的分数是这两部分的总和。
  • 输入和输出可以通过任何方便的方法给出。
  • 可以假定输入符合您语言的本机数字类型,但是,不能假定级联数字或输出都不能满足要求。
  • 完整的程序或功能都是可以接受的。如果是函数,则可以返回输出而不是打印输出。
  • 禁止出现标准漏洞
  • 这是因此所有常用的高尔夫规则都适用,并且最短的代码(以字节为单位)获胜。

可以接受数字列表吗?
Rod

在评估前导零的情况下产生最小伪造的测试用例可能是值得的-我认为9, 11, 3这样做是可以的。
乔纳森·艾伦

@Rod Yep,可以使用数字列表进行输出。
AdmBorkBork

@Rod我不知道您在说什么,我在上面清楚地键入了“输出”。;-)
AdmBorkBork

@JonathanAllan很好。添加。
AdmBorkBork

Answers:


5

Haskell,162个字节

l=length
((m,f)%n)s|n>=l s=[]|n>0,(p,c:r)<-span(/=m(f$take(n+1)s))s=c:((m,id)%(n-l p)$r)|1>0=s
(x#y)z=[p%z$show=<<[x..y]|p<-[(maximum,id),(minimum,filter(>'0'))]]

在线尝试!

使用jafe描述的算法。使用效率较低的方法可能会更短一些,但是编写起来更有趣:)

%操作采用4个参数(实际上是3个,但无论如何):m这是一个从列表中选择“最优”成员的函数(maximum或者minimum根据我们的需要);f这是一个“过滤器”功能;n剩下要减少的位数;和s字符串。首先,我们检查n是否等于字符串中剩余的位数(我>=为安全起见),然后删除其余的位数s。否则,我们检查是否仍然需要删除数字(n>0),然后span将字符串分成三部分:p要删除的数字,c最佳的可到达数字和r剩下的字符串。我们通过传递span谓词来做到这一点,该谓词对照我们的最佳数字检查是否相等。要找到该数字,我们采用n+1字符串的第一位数字,对其进行过滤,然后将其传递给我们的“ chooser”函​​数。现在,我们只求出最佳数字并递归,p从中减去的长度(被丢弃的数字数)n。请注意,我们没有将过滤功能传递给递归调用,而是将其替换为id。这是因为minimum仅在第一次迭代时才使用过滤器,以避免选择前导0 。之后,我们不再需要任何过滤器。

%真的只是一个辅助功能#是我们的“真实”的功能,同时xyz。我们使用列表理解只是为了避免重复,它遍历了我们的函数元组,并将它们%z和串接的字符串一起传递给了。该字符串是使用magic monad运算符创建的(=<<),在这种情况下,其运算符类似于concatMap


3

果冻,17个字节

r/VDœcL_¥¥ḷ/ƇVṢ.ị

在线尝试!

计算所有可能性,然后保持最大和最小。

左参数:x,y构造范围。正确的参数:z要删除的数字。

r/VDœcL_¥¥ḷ/ƇVṢ.ị
r/                 Inclusive range from x to y
  V                Concatenate the digits together
   D               Get the resulting digits
         ¥         Dyad:
        ¥            Dyad:
      L                Length of the list of digits in the concatenated number.
       _               Subtract the number of digits to be removed.
    œc               Combinations without replacement. (remove z digits)
            Ƈ      Keep lists of digits that:
          ḷ/       have a positive first element (no leading zeros).
             V     Combine digits into integers. (vectorizes to ldepth 1)
              Ṣ    Sort the numbers
               .ị  Indexes at value 0.5 which yields the first and last elements.

2

Python 2 143字节

import itertools
s,e,r=input()
l=''.join(map(str,range(s,e+1)))
L=[i for i in itertools.combinations(l,len(l)-r)if'0'<i[0]]
print min(L),max(L)

在线尝试!

通过计算目标大小的所有组合(保留元素顺序)并从中获取最小/最大数字来工作


哦...我想这很有用。我非常努力地制作一个可以确定性地计算出来的程序。
Don Thousand

@RushabhMehta蛮力计算仍然是确定性的,只是速度较慢。
dylnan '18

2

木炭,56个字节或21 + 46 35 = 67 56个字节

≔⪫…·NNωθFN≔⌈EθΦθ⁻λνθθ

在线尝试!链接是详细版本的代码。说明:

≔⪫…·NNωθ

输入xy,创建一个包含范围,并将数字连接成字符串。

FN

循环一次以删除每个数字。

≔⌈EθΦθ⁻λνθ

创建一个通过从当前字符串中删除每个可能的字符并取其最大值而形成的字符串列表。

θ

打印结果。

≔⪫…·NNωθF⊕N⊞υωΦθ∧⁼ι⌊Φ✂θκLυ¹∨κIλ⊞Oυω

在线尝试!链接是详细版本的代码。说明:

≔⪫…·NNωθ

输入xy,创建一个包含范围,并将数字连接成字符串。

F⊕N⊞υω

输入z并递增。然后,我创建一个该长度的列表:我需要能够z在下面的过滤器中递增,但是只允许命令递增变量。有一个漏洞,PushOperator增加了列表的长度。

 θ                      String of digits
Φ                       Filter over characters
         κ              Current index
          Lυ            Length of list i.e. current `z` value
            ¹           Literal 1
       ✂θ               Slice string of digits
      Φ                 Filter over characters
              κ         Outer index
               Iλ       Cast inner character to number
             ∨          Logical OR
     ⌊                  Minimum
   ⁼ι                   Equals the outer character
  ∧              ⊞Oυω   And also push to list i.e. increment `z`
                        Implicitly print

通过检查可切片区域中是否没有低位字符来过滤所需的字符。该区域从第一个z+1字符开始(因为必要时可以将第一个字符切开z),并且每个保留的字符的端点都会递增。注意不要为第一个字符选择零。

当用于计算最大可能数时,更快的算法为30个字节:

≔⪫…·NNωθF⊕N⊞υωΦθ∧⁼ι⌈✂θκLυ¹⊞Oυω

在线尝试!链接是详细版本的代码。编辑:从那时起,我已经能够将上述两个结合成第二个56字节的解决方案,该解决方案会生成两个结果:

≔⪫…·NNωθF⊕N⊞υω≔⮌υη⟦Φθ∧⁼ι⌈✂θκLυ¹⊞OυωΦθ∧⁼ι⌊Φ✂θκLη¹∨κIλ⊞Oηω

在线尝试!链接是详细版本的代码。说明:

≔⪫…·NNωθ

生成初始字符串。

F⊕N⊞υω

表示z+1为列表的长度。

≔⮌υη

反转列表,从而将其克隆并保存结果。

将两个结果打印在单独的行上。(另一种方法是用文字\r字符分隔结果。)

Φθ∧⁼ι⌈✂θκLυ¹⊞Oυω

生成最大可能的数字。

Φθ∧⁼ι⌊Φ✂θκLη¹∨κIλ⊞Oηω

使用克隆的列表生成尽可能小的数字,以跟踪z


1

果冻 19  18 字节

rDẎœcL_⁵Ɗ$ị@Ƈ1ḌṢ.ị

在线尝试!

非常低效,绝对没有意义,1, 100, 100因为(19292)=305812874887035355118559193163641366325011573739619723360


1

05AB1E,16 个字节

ŸSDg³-.Æʒ¬Ā}{Ć`‚

在线尝试!

完整程序,按以下顺序读取输入:y,x,z。输出两个字符列表。

说明

ŸSDg³-.Æʒ¬Ā}{Ć`‚    Full program. Inputs: y, x, z.
Ÿ                   Inclusive binary range from x to y. Push [x ... y].
 S                  Dump the digits separately in a list.
  Dg                Duplicate, and use the second copy to get its length.
    ³-              Subtract z from the length.
      .Æ            Retrieve all combinations of length - z elements from the digits.
        ʒ  }        Keep only those that...
         ¬Ā         Don't start with a 0 (head, then Python-style boolean).
            {       Sort the remaining elements.
             Ć      Enclose. Pushes list + list[0] (appends its tail to itself)
              `     Dump all elements separately on the stack.
               ,    Pair, to get the last two, min and max (after enclosing)

哦,Ć`‚很聪明,很不错的答案!
凯文·克鲁伊森

0

Matlab,95个字节

function[m]=f(s,e,c),a=sprintf('%d',s:e);x=str2num(combnk(a,length(a)-c));m=[min(x),max(x)];end

在线尝试!

返回带有最小值和最大值的1x2矩阵。

怎么运行的

% Full code
function[m]=f(s,e,c),a=sprintf('%d',s:e);x=str2num(combnk(a,length(a)-c));m=[min(x),max(x)];end

% The function
function[m]=f(s,e,c),                                                                       end

                     % Creates the range in a single string
                     a=sprintf('%d',s:e);

                                                   % Gets all the combinations
                                                   combnk(a,length(a)-c)

                                         % Converts the string combinations to integers
                                         x=str2num(                     );

                                                                          % Finds min and max
                                                                          m=[min(x),max(x)];
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.