สนุกกับการเรียงสับเปลี่ยน


17

ใครไม่รักการเรียงสับเปลี่ยนใช่ไหม? ฉันรู้ว่ามันยอดเยี่ยมมาก - สนุกมาก!

ดีทำไมไม่ใช้เวลานี้สนุกและทำให้มันfunner ?

นี่คือความท้าทาย:

รับอินพุตในรูปแบบที่แน่นอน: nPr, ซึ่งnเป็นพูลที่นำมาจากและrเป็นจำนวนการเลือกจากพูลนั้น (และnและrเป็นจำนวนเต็ม) เอาต์พุต / ส่งกลับจำนวนพีชคณิตที่แน่นอน สำหรับผู้ที่มีสนิมเล็กน้อยกับคำศัพท์: การเปลี่ยนแปลง, การกำหนด 2a

อย่างไรก็ตามนี่คือที่มาของความท้าทาย (ทำให้ไม่ง่ายเกินไป):

คุณไม่สามารถใช้ไลบรารีเฟรมเวิร์กหรือเมธอดสำหรับฟังก์ชันการเรียงลำดับของคุณ คุณไม่สามารถใช้วิธีแบบแฟคทอเรียลวิธีการเรียงสับเปลี่ยนหรืออะไรก็ได้ คุณต้องเขียนทุกอย่างด้วยตัวเอง

หากต้องการคำชี้แจงเพิ่มเติมโปรดอย่าลังเลที่จะบอกฉันในความคิดเห็นและฉันจะทำตามทันที


นี่คือตัวอย่าง I / O:

ฟังก์ชั่นตัวอย่างคือ permute(String) -> int

การป้อนข้อมูล:

permute("3P2")

เอาท์พุท:

6

นี่คือรหัส - กอล์ฟดังนั้นรหัสที่สั้นที่สุดชนะ!


2
Aww ผมคิดว่าสิ่งที่ท้าทายนี้จะเป็นในกลุ่มการเปลี่ยนแปลง สิ่งที่เย็น. นี่ก็เจ๋งเหมือนกันและเกี่ยวข้องอย่างใกล้ชิดกับกลุ่มการเปลี่ยนแปลง รักความท้าทาย
Justin

เมื่อคุณบอกว่าไม่มีวิธีการในตัวหรือห้องสมุดคุณหมายถึงวิธีการเรียงสับเปลี่ยนหรือเพื่ออะไร? ฉันสามารถใช้ในตัวsplitที่จะแยกการป้อนข้อมูลที่P? ฟังก์ชั่นที่แปลงสตริงเป็นตัวเลขคืออะไร
xnor

3
คำตอบอาจสมมติว่า0 <= r <= n?
Peter Taylor

1
@Dopapp คุณหมายความว่าr ไม่มากกว่าnใช่หรือไม่
เดนนิส

1
@RetoKoradi - ฉันคิดว่าในความพยายามที่จะไม่บังคับให้ผู้โพสต์ส่วนใหญ่ทำซ้ำคำตอบของพวกเขาคุณไม่ได้รับอนุญาตให้ใช้แฟกทอเรียลหรือวิธีการเปลี่ยนรูปแบบ / ฟังก์ชัน
Daniel

คำตอบ:


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

@feersum มันตั้งค่า$\เป็น1(ถ่าน 49, octal 61)
โม่

3

Haskell, 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ประโยค


2

Minkolang 0.11 , 13 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

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->...เรียกว่าให้มันชื่อเช่น

Ungolfed:

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

สิ่งนี้ใช้ความจริงที่ว่าจำนวนการเรียงสับเปลี่ยนคือn ( n -1) ( n -2) ... ( n - k +1)

บันทึก 10 ไบต์ต้องขอบคุณ Glen O!


ไม่จำเป็นต้องดังนั้นคุณก็สามารถใช้Int map(parse,...)
เกลน O

@GlenO ใจของฉันถูกพัด ฉันไม่ได้ตระหนักถึงIntความจำเป็นในสถานการณ์นั้น ขอบคุณมาก!
Alex A.

2

Bash + Linux utils, 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 เป็นจำนวนเต็ม แยกที่เป็นและn rแล้วแสดงสินค้าของทุกจำนวนเต็มในช่วงที่จะn-r+1 nสิ่งที่น่าสนใจนี้ใช้งานได้แม้จะxP0ให้คำตอบที่ถูกต้องเป็น 1 เพราะใน MATLAB prod()ฟังก์ชันจะคืนค่า 1 หากคุณลองทำผลิตภัณฑ์อาร์เรย์ที่ว่าง เมื่อใดก็ตามที่rเป็นศูนย์ช่วงจะเป็นอาร์เรย์ที่ว่างเปล่าดังนั้นบิงโกเราจะได้รับ 1


นอกจากนี้ยังทำงานได้อย่างสมบูรณ์แบบกับอ็อกเทฟเช่นกัน คุณสามารถลองออนไลน์ได้ที่นี่



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.

ฟังก์ชั่นขุดแร่ที่ผมใช้ในชายแดนอาจนับเป็นในตัว ... มันอยู่ที่ไหนสักแห่งระหว่างทั่วไปของผู้ประกอบการคูณและความจำเพาะของผู้ประกอบการแฟกทอที่


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

Python 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

@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

Ouroboros , 47 45 ไบต์

สิ่งนี้น่าเกลียดมาก - ฉันคิดว่ามันน่าจะเล่นกอล์ฟต่อไป

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

โค้ดแต่ละบรรทัดใน Ouroboros แสดงถึงงูที่กินหาง

งู 1

Sสลับเป็นสแต็กที่แบ่งใช้ r.rอ่านหมายเลขหนึ่งทำซ้ำและอ่านอีกหมายเลขหนึ่ง (อักขระที่ไม่ใช่Pตัวเลขเช่นถูกข้ามไป) -ลบทั้งสอง ถ้าใส่เป็น7P2ตอนนี้เรามี7, 5ในสแต็คที่ใช้ร่วมกัน สุดท้าย1(กินตัวละครสุดท้ายของงู เนื่องจากนี่คือตัวละครที่ตัวชี้คำสั่งใช้งานอยู่งูจึงตาย

งู 2

)sไม่ทำอะไรเลยเป็นครั้งแรกผ่าน .!+ทำซ้ำด้านบนของสแต็คของงู 2 ตรวจสอบว่ามันเป็นศูนย์และถ้าเป็นเช่นนั้นเพิ่ม 1 ในการทำซ้ำครั้งแรกสแต็กจะว่างเปล่าและได้รับการปฏิบัติราวกับว่ามันมีศูนย์อนันต์ดังนั้นนี้ผลัก1 ; ในการวนซ้ำในภายหลังสแต็กมีค่าที่ไม่ใช่ศูนย์และไม่มีผลใด ๆ

ถัดไปSเปลี่ยนเป็นสแต็กที่แชร์ซึ่งเรามีหมายเลขnและตัวนับสำหรับการคำนวณผลิตภัณฑ์ 1+เพิ่มตัวนับ .@@.@\<!ทำซ้ำทั้งตัวเลขและกด 1 หากnยังคงมากกว่าหรือเท่ากับตัวนับ 0 มิฉะนั้น @@*Yจากนั้นคูณตัวนับตามปริมาณนี้และโยนสำเนาลงในสแต็คของงู 2

s.!+สลับกลับไปที่สแต็คของ snake 2 และใช้รหัสเดียวกันกับรุ่นก่อนหน้าเพื่อแปลงหมายเลขบนสุดเป็น 1 หากเป็น 0 และคงไว้เหมือนเดิม แล้วก็*คูณผลลัพธ์ด้วยผลิตภัณฑ์บางส่วนที่อยู่บนสแต็กนี้

ตอนนี้เรากลับไปที่ stack stack ( S), ทำซ้ำ counter-or-zero ( .), และ negate มันสองครั้ง ( !!) เพื่อเปลี่ยนตัวนับ nonzero เป็น 1. 4*.(คูณนี่ด้วย 4, ทำซ้ำและกินอักขระจำนวนมากจาก จุดจบของงู

  • หากเรายังไม่ถึงสถานะหยุดพักเราจะได้ 4 ในสแต็ก ตัวละครสี่ตัวหลัง(ถูกกินและควบคุมวนไปรอบ ๆ จุดเริ่มต้นของรหัส ที่นี่)regurgitates ตัวละครสี่ตัวsสลับกลับไปที่กองของงู 2 และดำเนินการต่อไป
  • ถ้าตัวนับผ่านไปnเรามี 0 บนสแต็กและไม่มีอะไรกิน snสลับไปที่กองซ้อนของงู 2 และส่งออกค่าสูงสุดเป็นตัวเลข จากนั้น1(กินอักขระตัวสุดท้ายและตาย

ผลที่ได้คือผลิตภัณฑ์ที่(r+1)*(r+2)*...*nมีการคำนวณและส่งออก

ลองดู

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.