有趣的排列


17

谁不绝对喜欢排列,对吗?我知道,它们很棒-非常有趣!

好吧,为什么不把这个乐趣变得有趣呢?

这是挑战:

给定精确格式的输入:nPr,其中n是从中获取的池,r是从该池中选择的项的数量(and nr是整数),输出/返回排列的确切数量。对于那些对术语有些生疏的人:排列,定义。2a

但是,这是挑战发挥作用的地方(使其变得不太容易):

您不能将任何内置库,框架或方法用于您的置换功能。您可能不使用阶乘方法,置换方法或任何种类的方法;您必须自己编写所有内容。

如果需要进一步澄清,请随时在评论中告诉我,我将立即采取行动。


这是一个I / O示例:

样本函数为 permute(String) -> int

输入:

permute("3P2")

输出:

6

这是代码高尔夫球,所以最短的代码胜出!


2
w 我认为这个挑战将在排列组上。酷的东西。这也很酷,并且与排列组紧密相关。喜欢挑战。
贾斯汀

当您说没有内置方法或库方法时,是指排列,还是任何其他意思?我可以使用内置的split拆分输入P吗?将字符串转换为数字的函数呢?
xnor

3
答案可以假设0 <= r <= n吗?
彼得·泰勒

1
@Dopapp您的意思是r 大于n吗?
丹尼斯2015年

1
@RetoKoradi-我想为了不强迫大多数张贴者重做他们的答案,只是不允许您使用任何阶乘或置换方法/功能。
丹尼尔(Daniel)

Answers:


4

CJam,15个 14字节

r~\;~\),>UXt:*

CJam解释器中在线尝试。

怎么运行的

r              e# Read a token ("nPr") from STDIN.
 ~             e# Evaluate. This pushes the numbers n, Pi and r on the stack.
  \;           e# Discard Pi.
    ~          e# Take the bitwise NOT of r. Pushes -(r+1).
     \)        e# Increment n.    
       ,       e# Turn n+1 into [0 ... n].
        >      e# Keep only the last r+1 elements.
         UXt   e# Replace the first element with 1.
               e# This avoid dealing with the egde case nP0 separately.
            :* e# Compute their product.

4

Perl,27个字节

#!perl -pl61
$\*=$`-$%++for/P/..$'}{

将shebang计为4,输入来自stdin。


样品用量

$ echo 3P2 | perl npr.pl
6

$ echo 7P4 | perl npr.pl
840

什么样的选择是l61
feersum 2015年

@feersum设置$\1(字符49,八进制61)。
2015年

3

哈斯克尔, 71 66个字节

p s|(u,_:x)<-span(/='P')s,(n,k)<-(read u,read x)=product[n-k+1..n]

很简单的东西:在“ P”处拆分,然后取(n-k + 1)与n之间的乘积。

感谢nimi提出使用模式卫士而不是where子句的想法,它节省了5个字节。


2

Minkolang 0.1113 25 19个字节

感谢Sp3000提出的建议!

1nnd3&1N.[d1-]x$*N.

在这里尝试。

说明

1        Push 1
n        Take integer from input (say, n)
n        Take integer from input (say, k); ignores non-numeric characters in the way
d3&1N.   Output 1 if k is 0
[   ]    Loop k times
 d1-     Duplicate top of stack and subtract 1
x        Dump top of stack
$*       Multiply all of it together
N.       Output as integer

这使用与Alex相同的算法:n P k= n(n-1)(n-2)...(n-k+1)


2

朱莉娅63 58 48字节

s->((n,r)=map(parse,split(s,"P"));prod(n-r+1:n))

这将创建一个未命名的函数,该函数接受字符串并返回整数。要给它起个名字,例如f=s->...

取消高尔夫:

function f(s::AbstractString)
    # Get the pool and number of selections as integers
    n, r = map(parse, split(s, "P"))

    # Return the product of each number between n-r+1 and n
    return prod(n-r+1:n)
end

这利用了排列数为nn -1)(n -2)...(n - k +1)的事实。

感谢Glen O,节省了10个字节!


不需要Int,所以您可以使用map(parse,...)
Glen O

@GlenO我的想法已经震撼了。我没有意识到Int在那种情况下是必要的。非常感谢!
Alex A.

2

Bash + Linux实用程序,33

jot -s\* ${1#*P} $[${1/P/-}+1]|bc

jot产生以r开头的整数序列n-r+1,并用分隔它们*。该表达式通过管道传递bc给算术评估。


1

MATLAB,54个字节

[n,r]=strread(input(''),'%dP%d');disp(prod((n-r+1):n))

试图使其更小,但是MATLAB真正不擅长的事情之一就是获取输入。仅需32个字符即可从输入字符串中获得两个数字!

相当自我解释的代码。以%dP%d%d为整数的形式获取输入。将其拆分为nr。然后显示范围n-r+1为到的每个整数的乘积n。有趣的是,即使xP0给出正确答案为1,该方法也有效。这是因为在MATLAB中,prod()如果尝试执行空数组的乘积,该函数将返回1。每当r为零时,范围将是一个空数组,因此宾果游戏得到1。


这也适用于Octave。您可以在这里在线尝试。


1

Javascript,59 57字节

s=>(f=(n,k)=>k?(n- --k)*f(n,k):1,f.apply(f,s.split('P')))

1

Java(594-字节)

import java.util.*;import java.lang.*;public class Perm {private String a;private static int[] nr=new int[2];private static int sum=1;Scanner in=new Scanner(System.in);public String input(){a=in.nextLine();return a;}public void converter(String a){this.a=a;String b=a.substring(0,1);String c=a.substring(2);nr[0]=Integer.parseInt(b);nr[1]=Integer.parseInt(c);}public int param(){for(int counter=0; counter < nr[1]; counter++){sum=sum*nr[0]--;}return sum;}public static void main(String args[]){Perm a;a=new Perm();String k=a.input();a.converter(k);int ans=a.param();System.out.println(ans);}}

1

J,23个字节

^!._1/@(".;._1)@('P'&,)

匿名函数。例:

   f =. ^!._1/@(".;._1)@('P'&,)
   f '10P4'
5040

说明:

       (  ;._1)@('P'&,)   Split over 'P', and on each slice,
        ".                read a number.
      @                   Then,
^!._1/                    fold (/) with the built-in "stope function" (^!.k) for k=1.

我使用的stope函数可能会算作内置函数。它位于乘法运算符的一般性与阶乘运算符的特殊性之间。


1

APL,23

{{×/⍵↑⍳-⍺}/-⍎¨⍵⊂⍨⍵≠'P'}

将字符串作为参数。说明:

              ⍵⊂⍨⍵≠'P'  ⍝ Split by 'P'.
           -⍎¨          ⍝ Convert to numbers and negate making a vector (−n −r)
 {       }/             ⍝ Reduce it by a defined function, which
      ⍳-⍺               ⍝ makes a vector of numbers from 1 to n (⍺)
    ⍵↑                  ⍝ takes r last elements (⍵←−r)
  ×/                    ⍝ and multiplies them together.

这是哪个APL?我的Dyalog副本出现错误。
lirtosiast

1
@ThomasKwa ⎕ML←3在Dyalog中使用。
user46915

1

蟒蛇2,66

def f(s):a,b=map(int,s.split('P'));P=1;exec"P*=a;a-=1;"*b;print P

非常简单。将输入的数字处理为a,b。保持运行产品为P,乘以的第一ba, a-1, a-2, ...


2
我看不到怎么input()不会导致错误。
feersum 2015年

@feersum我尝试过,它确实引发了语法错误。
Alex A.

我当时使用带引号的输入("3P2"我认为通常是允许使用的),但是在这里,挑战显示为“采用精确形式的输入”,因此我将其更改为采用字符串的函数。
xnor

1

TI-BASIC,52字节

Ans→Str1
expr(sub(Ans,1,⁻1+inString(Ans,"P→P        ;n
1
If expr(Str1                               ;If n^2*r ≠ 0
prod(randIntNoRep(P,P+1-expr(Str1)/P²
Ans

TI-BASIC具有“列表产品”功能,因此绕过内建函数的限制并不难。但是,TI-BASIC不支持空列表,因此我们需要

为了提取两个数字,我提取了第一个数字作为子字符串。这很贵 ; 它占据了整个第二行。为了避免再次对第二个数字执行此操作,我将变量P设置为该数字,并使用评估整个字符串expr(,然后除以P²。

最后,我对两个数字之间的列表进行了随机排列(小心地将一个数字添加到第二个数字)并乘积。


1

衔尾蛇47 45字节

其中一些非常丑陋-我想它可以打得更远。

Sr.r-1(
)s.!+S1+.@@.@\<!@@*Ys.!+*S.!!4*.(sn1(

Ouroboros中的每一行代码都代表一条蛇在吞食它的尾巴。

蛇1

S切换到共享堆栈。r.r读取一个数字,将其复制,然后读取另一个。(P跳过非数字字符。)-将两者相减。如果输入的是7P2,我们现在有75共享堆栈。最后,1(吃掉蛇的最后角色。由于这是指令指针所在的字符,因此蛇会死亡。

蛇2

)s第一次没有做任何事情。.!+复制蛇2堆栈的顶部,检查其是否为零,如果为零,则加1。在第一次迭代中,堆栈为空,并视为包含无限零,因此此操作按入1;在以后的迭代中,堆栈包含一个非零值,这无效。

接下来,S切换到共享堆栈,在该堆栈中我们有数字n和用于计算乘积的计数器。1+递增计数器。.@@.@\<!同时复制两个数字,如果n仍大于或等于计数器,则按1 ,否则按0。@@*Y然后将计数器乘以该数量,然后将副本复制到蛇2的堆栈中。

s.!+切换回蛇2的堆栈,并使用与之前相同的代码将顶号转换为1(如果为0),否则保持不变。然后*将结果乘以该堆栈上的部分乘积。

现在,我们回到共享堆栈(S),复制counter-or-zero(.),并将其取反两次(!!),以将非零计数器变成1。将其4*.(乘以4,得到重复,然后从蛇的尽头。

  • 如果我们还没有达到停止状态,那么我们的筹码就是4。后面的四个字符(被吃掉,并且控制循环到代码的开头。在此)重新定义四个字符,s切换回蛇2的堆栈,然后继续执行。
  • 如果计数器已通过n,则堆栈上将有一个0,并且什么也没吃。sn切换到蛇2的堆栈并输出最大值作为数字;然后1(吃最后一个角色而死。

结果是乘积(r+1)*(r+2)*...*n被计算并输出。

试试看

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.