จำนวนรอบของการเปลี่ยนแปลง


23

พิจารณาการเปลี่ยนแปลงของจำนวนเต็ม1, ... n, เช่นนี้สำหรับn = 6:

[5,2,4,3,6,1]

ถ้าคุณดูการเปลี่ยนแปลงเช่นการทำแผนที่จาก[1,2,3,4,5,6]ไป[5,2,4,3,6,1], การเปลี่ยนแปลงสามารถ decomponsed เข้าไปเคลื่อนรอบ รอบเป็นส่วนย่อยขององค์ประกอบที่แมปกัน ยกตัวอย่างเช่น1ได้รับการแมปไป5ซึ่งได้รับการแมปไปซึ่งได้รับการแมปกลับไป6 ดังนั้นหนึ่งรอบเป็น1 [1,5,6]รอบอื่น ๆและ[2] [3,4]ดังนั้นจำนวนรอบ3สำหรับการเปลี่ยนแปลงนี้คือ

โดยทั่วไปรอบของการเปลี่ยนแปลงที่จะไม่ซ้ำกัน (ถึงการสั่งซื้อ) และจำนวนรอบสำหรับการเปลี่ยนแปลงของขนาดที่nแตกต่างกันจากการ1n

ความท้าทาย

รับการเปลี่ยนแปลงที่ไม่ว่างเปล่าส่งออกจำนวนรอบ

การป้อนข้อมูลเป็นอาร์เรย์ที่เกิดขึ้นจากnจำนวนเต็ม1, 2, ... , ที่n n > 0จำนวนเต็มแต่ละค่าเกิดขึ้นเพียงครั้งเดียว ลำดับที่ปรากฏจะกำหนดการเปลี่ยนลำดับตามตัวอย่างด้านบน

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

สำหรับการเปลี่ยนแปลงของขนาดnแทนที่จะเป็น 1 ชุดตามของจำนวนเต็ม1, ... , nคุณสามารถอย่างต่อเนื่องใช้ชุด 0-based 0, ... n-1, ถ้าเป็นเช่นนั้นโปรดระบุไว้ในคำตอบของคุณ

รหัสควรใช้งานnได้สูงสุด20ในเวลาที่เหมาะสมพูดน้อยกว่าหนึ่งนาที

รหัสกอล์ฟ อนุญาตบิวอินได้ทั้งหมด

กรณีทดสอบ

สิ่งนี้จะถือว่าอินพุตแบบอิงอาร์เรย์ 1 ตัว

 [1] -> 1
 [3,2,1] -> 2
 [2,3,4,5,1] -> 1
 [5,2,4,3,6,1] -> 3
 [8,6,4,5,2,1,7,3] -> 2
 [4,5,11,12,7,1,3,9,10,6,8,2] -> 1
 [4,2,5,11,12,7,1,3,9,10,6,8] -> 5
 [5,8,6,18,16,9,14,10,11,12,4,20,15,19,2,17,1,13,7,3] -> 3
 [14,5,17,15,10,18,1,3,4,13,11,16,2,12,9,7,20,6,19,8] -> 7

ที่เกี่ยวข้อง

ความท้าทายที่เกี่ยวข้องนี้จะถามถึงวงจรที่แท้จริงของการเปลี่ยนแปลงไม่ใช่จำนวนของการเปลี่ยนแปลง ต้องการเพียงจำนวนรอบเท่านั้นที่สามารถนำไปสู่อัลกอริธึมที่สั้นกว่าซึ่งก้าวเท้าเลี่ยงการสร้างรอบจริง


ไม่ต้องห่วงคำถามของฉันมันระบุไว้ในคำถามที่ได้รับอนุญาตจากอินพุต 0
orlp

@ orlp นั่นเร็วมาก! ฉันไม่ได้เห็นคำถามของคุณเลย
Luis Mendo

เราสามารถทำแผนที่ดัชนีกับค่าเป็นอินพุตได้หรือไม่?
ทองแดง

1
@Copper ฉันคิดว่าใช่หากโดเมนของการจับคู่เป็นชุด1... nในลำดับนั้น คุณช่วยให้ชัดเจนว่าการแมปเป็นอินพุตได้อย่างไร? มันเป็นโครงสร้างข้อมูลหรือไม่?
Luis Mendo

@LuisMendo dictใช่มันเป็นโครงสร้างข้อมูลเช่นงูหลาม ฉันต้องการจะมี{1: 2, 2: 1}เป็น input [2, 1]แทน
ทองแดง

คำตอบ:


12

J, 4 ไบต์

#@C.

นี่ถือว่าการเปลี่ยนแปลงเป็นแบบ 0 มันใช้ builtin C.ซึ่งได้รับรายการที่แสดงถึงการเปลี่ยนแปลงโดยตรงของรายการรอบ จากนั้น#ประกอบขึ้น@บนที่ส่งกลับจำนวนรอบในรายการนั้น

ลองที่นี่


1
นั่นคือการโกง! :)
orlp

1
ฉันควรห้ามตัวอาคาร :-D
Luis Mendo

2
Builtins เป็นความรัก Builtins คือชีวิต ฉันเห็นด้วยว่ามันจะสนุกมากขึ้นถ้าตัวอาคารถูกแบน อย่าลังเลที่จะเปลี่ยนกฎทันทีก่อนตอบมากเกินไป
ไมล์

@miles Nah ฉันจะทิ้งมันอย่างที่เป็น เยี่ยมมาก!
Luis Mendo

7

JavaScript, 99 98 ไบต์

วิธีการแก้ปัญหานี้จะถือว่าอาร์เรย์และค่าของมันเป็นศูนย์ดัชนี (เช่น[2, 1, 0])

f=a=>{h={},i=c=0;while(i<a.length){s=i;while(!h[i]){h[i]=1;i=a[i]}c++;i=s;while(h[++i]);}return c}

คำอธิบาย

// assumes the array is valid and zero-indexed
var findCycles = (array) => {
    var hash = {};  // remembers visited nodes
    var index = 0;  // current node
    var count = 0;  // number of cycles
    var start;      // starting node of cycle

    // loop until all nodes visited
    while(index < array.length) {
        start = index;  // cache starting node

        // loop until found previously visited node
        while(!hash[index]) {
            hash[index] = 1;    // mark node as visited
            index = array[index];   // get next node
        }
        count++;    // increment number of cycles

        index = start + 1;  // assume next node is right after

        // loop until found unvisited node
        while(hash[index]) {
            index++;    // get next node
        }
    }

    return count;   // return number of cycles
};

3
ยินดีต้อนรับสู่ PPCG! คำตอบแรกที่ดี! นี่เป็นหนึ่งในคำตอบที่ดีที่สุดหากไม่ใช่คำตอบที่ดีที่สุดคำตอบแรกที่ฉันได้เห็นในประสบการณ์ของฉัน! ดีแล้วทำต่อไป!
GamrCorps

ว้าวขอบคุณมาก! ฉันต้องหาวิธีทำ lambdas ใน JavaScript ฉันยังไม่คุ้นเคยกับสิ่ง ES6
kamoroso94

6

Mathematica ขนาด 45 ไบต์

Length@ConnectedComponents@Thread[Sort@#->#]&

มันสร้างกราฟและนับองค์ประกอบที่เชื่อมต่อ


6

Mathematica, 37 28 27 ไบต์

#~PermutationCycles~Length&

ขอบคุณ @alephalpha สำหรับการบันทึก 9 ไบต์และ @miles สำหรับอีก 1 ไบต์


3
PermutationCycles[#,Length]&
alephalpha

3
โอ้นั่นมันเรียบร้อย ฉันไม่รู้ว่าPermutationCyclesสามารถใช้อาร์กิวเมนต์ที่สองเพื่อเปลี่ยนหัวของผลลัพธ์ #~PermutationCycles~Length&นอกจากนี้คุณยังสามารถใช้มัดสัญกรณ์ที่จะบันทึกไบต์อีก
ไมล์

1
นอกจากนี้ยังเกี่ยวกับโซลูชันดั้งเดิมของคุณ#&สั้นกว่าIdentityเล็กน้อย ;)
Martin Ender


5

เยลลี่12 10 9 ไบต์

ị³$ÐĿ«/QL

ที่บันทึกไว้ 1 ขอบคุณไบต์ @ เดนนิส

สิ่งนี้ใช้วิธีเรียงสับเปลี่ยนแบบ 1 มันทำงานโดยใช้การเปลี่ยนรูปแบบซ้ำ ๆ จนกว่าจะถึงการเปลี่ยนแปลงครั้งก่อนในขณะที่ยังรักษาค่าก่อนหน้า โดยการติดตามการเปลี่ยนแปลงมันจะสร้างวงโคจรสำหรับทุกค่าตามคอลัมน์ของตารางนั้น จากนั้นโดยการค้นหาขั้นต่ำหรือสูงสุดของแต่ละคอลัมน์สามารถสร้างป้ายกำกับสำหรับรอบนั้น จากนั้นให้ทำซ้ำรายการของป้ายกำกับและรับความยาวของฉลากซึ่งจะเป็นจำนวนรอบที่แยกออกจากกัน

ลองที่นี่

คำอธิบาย

ị³$ÐĿ«/QL  Input: permutation p
  $        Chain (ị³) as a monad
 ³           The input p
ị            For each value x, get the value at index x in p
   ÐĿ      Invoke it on p initially, and repeat it on its next value until it returns
           to a previous value and keep track of the results
           This will create a table where each column is the orbit of each value
     «/    Get the minimum value along each column of that table
       Q   Deduplicate
        L  Get the length and return

วิธีการที่ดีมาก!
Luis Mendo

ị³$ÐĿ«/QLควรทำงาน.
เดนนิส

@Dennis Wow นั่นเป็นกลลวงที่เรียบร้อย! เนื่องจากแต่ละรอบไม่ต่อเนื่องการใช้ค่าสูงสุด / นาทีและใช้เป็นป้ายกำกับจะเพียงพอที่จะลดความซ้ำซ้อน + ความยาวสำหรับผลลัพธ์
ไมล์

5

Python ขนาด 64 ไบต์

l=input()
for _ in l:l=[min(x,l[x])for x in l]
print len(set(l))

รหัส golfed นี้เกิดขึ้นเป็นสำนวนและสามารถอ่านได้ ใช้การจัดทำดัชนี 0

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

มันพอเพียงที่จะทำnซ้ำ หรืออีกวิธีหนึ่งเราสามารถทำซ้ำจนกว่ารายการจะไม่เปลี่ยนแปลงอีกต่อไป กลยุทธ์นี้ให้ฟังก์ชันการเรียกซ้ำที่มีความยาวเท่ากัน 64 ไบต์:

f=lambda l,p=0:len(set(l*(l==p)))or f([min(x,l[x])for x in l],l)

การลดคือ 65 ไบต์

lambda l:len(set(reduce(lambda l,_:[min(x,l[x])for x in l],l,l)))

การset(_)แปลงสามารถย่อให้สั้นลง{*_}ใน Python 3.5 ประหยัด 2 ไบต์


4

Haskell, 111 ไบต์

l!i|l!!i<0=l|1<2=(take i l++[-1]++drop(i+1)l)!(l!!i)
f(x:y)|x>=0=0|1<2=1+f y
c l|l==[-1|x<-l]=0|1<2=1+c(l!f l)

ใช้การจัดทำดัชนีแบบ 0


4
ประณามคุณดีขึ้นมีตัวอักษรเขียนโปรแกรมที่ดี :)1l!i|iIi!!1ll1|
orlp

@orlp และมีขนาด 111 ไบต์! : O
grooveplex

4

Pyth, 9 ไบต์

l{mS.u@QN

ใช้ดัชนีที่เป็น 0 ลองมันออนไลน์

มันทำงานอย่างไร

  m         map for d in input:
    .u        cumulative fixed-point: starting at N=d, repeatedly replace N with
      @QN       input[N]
              until a duplicate is found, and return all intermediate results
   S          sort
 {          deduplicate
l           length

3

JavaScript (ES6), 49 ไบต์

a=>a.reduce(g=(c,e,i)=>e<i?g(c,a[e],i):c+=e==i,0)

ใช้การทำดัชนีแบบ zero-based คำอธิบาย: reduceใช้เพื่อเรียกใช้ฟังก์ชันภายในของgแต่ละองค์ประกอบของอาร์เรย์ cคือการนับรอบ, eเป็นองค์ประกอบอาร์เรย์, iคือดัชนีอาร์เรย์ หากองค์ประกอบนั้นน้อยกว่าดัชนีก็จะเป็นวัฏจักรที่อาจเกิดขึ้นได้ - องค์ประกอบนั้นจะใช้ในการทำดัชนีเข้าไปในอาร์เรย์เพื่อค้นหาองค์ประกอบถัดไปในรอบการเรียกซ้ำ หากเราเริ่มต้นหรือจบด้วยดัชนีเดิมนี่คือรอบใหม่และเราเพิ่มจำนวนรอบ หาก ณ จุดใดเราพบว่ามีค่ามากกว่าดัชนีแล้วเราจะนับรอบนั้นในภายหลัง


เมื่อฉันเรียกใช้รหัสของคุณในอาร์เรย์[2,1,0,3,4,5]มันล้มเหลวด้วยข้อความนี้ "เกินขนาดสแต็กการโทรสูงสุด"
kamoroso94

1
@ kamoroso94 ขออภัยเกี่ยวกับสิ่งที่พิมพ์ผิดได้พุ่งเข้ามาควรได้รับการแก้ไขแล้ว
Neil

2

C, 90 ไบต์

โทรf()ด้วยintอาเรย์ที่ไม่แน่นอนซึ่งจัดทำดัชนีโดยอิง 1 พารามิเตอร์ที่สองคือขนาดของอาร์เรย์ ฟังก์ชันจะคืนค่าจำนวนรอบ

i,j,c;f(a,n)int*a;{for(c=i=0;i<n;++i)for(j=0,c+=!!a[i];a[i];a[i]=0,i=j-1)j=a[i];return c;}

ลองบน ideone

อัลกอริทึม:

For each index
    If index is non-zero
        Increment counter
        Traverse the cycle, replacing each index in it with 0.

2

GAP 30 ไบต์

ตรงไปตรงมาอาร์กิวเมนต์ที่สองที่Cyclesให้ค่าที่การเปลี่ยนแปลงควรกระทำ:

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