ปัญหาของฟัส (นับ)


29

ความท้าทาย

เขียนฟังก์ชั่นที่รับจำนวนเต็มบวกสองจำนวนnและkเป็นอาร์กิวเมนต์และส่งกลับจำนวนของคนสุดท้ายที่เหลือจากnหลังจากนับคนk -th แต่ละคน

นี่เป็นความท้าทายของนักเล่นกอล์ฟดังนั้นรหัสที่สั้นที่สุดชนะ

ปัญหา

nคน (หมายเลขจาก1ถึงn ) ยืนเป็นวงกลมและแต่ละk -th นั้นถูกนับจนกระทั่งเหลือคนเดียว (ดูบทความวิกิพีเดียที่เกี่ยวข้อง ) กำหนดจำนวนคนสุดท้ายนี้

เช่นสำหรับk = 3คนสองคนจะถูกข้ามและคนที่สามจะถูกนับออก คือสำหรับn = 7หมายเลขจะถูกนับในลำดับที่ 3 6 2 7 5 1 (ในรายละเอียด1 2 3 4 5 6 7 1 2 4 5 7 1 4 5 1 4 1 4 ) และทำให้คำตอบคือ4

ตัวอย่าง

J(7,1) = 7      // people are counted out in order 1 2 3 4 5 6 [7]
J(7,2) = 7      // people are counted out in order 2 4 6 1 5 3 [7]
J(7,3) = 4      // see above
J(7,11) = 1
J(77,8) = 1
J(123,12) = 21

คำตอบ:


5

GolfScript ขนาด 17 ไบต์

{{@+\)%}+\,*)}:f;

ใช้n kกับสแต็กและทิ้งผลลัพธ์ไว้บนสแต็ก

การผ่า

สิ่งนี้ใช้การเกิดซ้ำg(n,k) = (g(n-1,k) + k) % nกับg(1, k) = 0(ตามที่อธิบายไว้ในบทความ Wikipedia) ด้วยการเรียกซ้ำที่ถูกแทนที่ด้วยการพับซ้ำ

{          # Function declaration
           # Stack: n k
  {        # Stack: g(i-1,k) i-1 k
    @+\)%  # Stack: g(i,k)
  }+       # Add, giving stack: n {k block}
  \,*      # Fold {k block} over [0 1 ... n-1]
  )        # Increment to move from 0-based to 1-based indexing
}:f;

คุณสามารถเพิ่มคำอธิบายได้ไหม
Sherlock9

@ Sherlock9 ฉันจัดการเพื่อหาสิ่งที่ฉันทำแม้จะผ่านไป 3.5 ปีแล้วก็ตาม ใครบอกว่า GolfScript เป็นแบบอ่านอย่างเดียว ;)
Peter Taylor

เสียงกระแอม s / อ่าน / เขียน /
ปีเตอร์เทย์เลอร์

ขอโทษ ฉันเพิ่งเริ่มเรียนรู้ Golfscript เมื่อสองหรือสามวันที่ผ่านมาและฉันทุกครั้งที่ฉันอ่านรหัสของคุณฉันคิดอยู่เสมอว่าจะพลาดอะไรบางอย่างไป ... ตกลงฉันยังคงหายไปบางวิธีการที่ไม่พับ{k block}มากกว่า[0..n-1]ให้คุณได้รับg(0,k) 0 kที่จะเริ่มต้นด้วย? ขออภัยหากฉันโพสต์คำถามเหล่านี้ผิดที่
Sherlock9

@ Sherlock9 งานพับ pairwise 0 1 blockดังนั้นสิ่งแรกที่มันไม่สามารถประเมินผลการศึกษา g(1, k) (2-1) blockสะดวกมากที่จะเกิดขึ้น ดังนั้นจึงเริ่มต้นที่มากกว่าg(1,k) 1 g(0,k) 0แล้วหลังจากที่ดำเนินการบล็อกมันดันรายการถัดไปจาก array ( 2) และดำเนินการป้องกันอีกครั้ง ฯลฯ
ปีเตอร์เทย์เลอร์

14

เครื่องลงทะเบียน Minsky (ไม่หยุด 25 สถานะ)

ไม่ใช่ในทางเทคนิคฟังก์ชั่น แต่มันอยู่ในกระบวนทัศน์การคำนวณที่ไม่มีฟังก์ชั่นต่อ se ...

นี่เป็นความแตกต่างเล็กน้อยในกรณีทดสอบหลักของความท้าทายในการตีความ MRMครั้งแรกของฉัน: ปัญหา Josephus เป็นเครื่องลงทะเบียน Minsky

อินพุตในรีจิสเตอร์nและk; เอาท์พุทในการลงทะเบียนr; มันจะสันนิษฐานว่าr=i=t=0เมื่อเข้า คำสั่งหยุดสองคำแรกคือกรณีที่มีข้อผิดพลาด


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

ผมคิดว่าวิธีการอื่น ๆ : ถ้าแล้วk=1 r=0อืมผมต้องคิดเกี่ยวกับเรื่องนี้อีกครั้ง ...
ฮาวเวิร์ด

เมื่อฉันอ่านไดอะแกรมของคุณiจะนับจาก2ไปจนถึงnขณะrที่รีจิสเตอร์ซึ่งสะสมผลลัพธ์
Howard

@Howard ฉันค้นหาความคิดเห็นที่ฉันทำเมื่อฉันเขียนสิ่งนี้ครั้งแรกและคุณพูดถูก อ๊ะ ตอนนี้แก้ไขแล้ว (ฉันเชื่อว่า - จะทดสอบให้ละเอียดยิ่งขึ้นในภายหลัง)
Peter Taylor

7

Python 36

ฉันยังใช้สูตรจากวิกิพีเดีย:

J=lambda n,k:n<2or(J(n-1,k)+k-1)%n+1

ตัวอย่าง:

>>> J(7,3)
4
>>> J(77,8)
1
>>> J(123,12)
21


5

C, 40 ตัวอักษร

นี่เป็นเพียงสูตรที่บทความวิกิพีเดียเชื่อมโยงไปถึง:

j(n,k){return n>1?(j(n-1,k)+k-1)%n+1:1;}

เพื่อความหลากหลายนี่คือการติดตั้งที่ใช้การจำลอง (99 ตัวอักษร)

j(n,k,c,i,r){char o[999];memset(o,1,n);for(c=k,i=0;r;++i)(c-=o[i%=n])||(o[i]=!r--,c=k);
return i;}

4
บันทึกตัวละคร: j(n,k){return--n?(j(n,k)+k-1)%-~n+1:1;}.
ugoren

5

dc, 27 ไบต์

[d1-d1<glk+r%1+]dsg?1-skrxp

ใช้การเกิดซ้ำจากบทความ Wikipedia คำอธิบาย:

# comment shows what is on the stack and any other effect the instructions have
[   # n
d   # n, n
1-  # n-1, n
d   # n-1, n-1, n
1<g # g(n-1), n ; g is executed only if n > 1, conveniently g(1) = 1
lk+ # g(n-1)+(k-1), n; remember, k register holds k-1
r%  # g(n-1)+(k-1) mod n
1+  # (g(n-1)+(k-1) mod n)+1
]
dsg # code for g; code also stored in g
?   # read user input => k, n, code for g
1-  # k-1, n, code for g
sk  # n, code for g; k-1 stored in register k
r   # code for g, n
x   # g(n)
p   # prints g(n)

4

J, 45 ตัวอักษร

j=.[:{.@{:]([:}.]|.~<:@[|~#@])^:(<:@#)>:@i.@[

ทำการจำลอง

อีกทางเลือกหนึ่งโดยใช้สูตร (31 ตัวอักษร):

j=.1:`(1+[|1-~]+<:@[$:])@.(1<[)

ฉันหวังว่าฮาวเวิร์ดไม่รังเกียจว่าฉันได้ปรับรูปแบบการป้อนข้อมูลเล็กน้อยเพื่อให้เหมาะกับคำกริยา dyadic ใน J

การใช้งาน:

   7 j 3
4
   123 j 12
21

4

GolfScript, 32 24 ไบต์

:k;0:^;(,{))^k+\%:^;}/^)

การใช้งาน: คาดว่าทั้งสองพารามิเตอร์nและkจะอยู่ในสแต็กและปล่อยค่าเอาท์พุท

(ขอบคุณ Peter Taylor ที่แนะนำวิธีการวนซ้ำและเคล็ดลับอื่น ๆ อีกมากมาย)

วิธีการแบบเก่า (แบบเรียกซ้ำ) ของ 32 ตัวอักษร:

{1$1>{1$(1$^1$(+2$%)}1if@@;;}:^;

นี่คือ GolfScript แรกของฉันดังนั้นโปรดแจ้งให้เราทราบการวิจารณ์ของคุณ


1
1-มี (opcode ในทำนองเดียวกันคือ1+ )คุณไม่ต้องใช้ตัวอักษรสำหรับการจัดเก็บเพื่อให้คุณสามารถใช้เช่น^แทนJและไม่จำเป็นต้องใช้พื้นที่หลังจากที่มัน คุณมีมากขึ้น$s กว่าเป็นปกติในโปรแกรมที่ดีแข็งแรงเล่นกอล์ฟ: \@.พิจารณาว่าคุณสามารถลดได้โดยใช้การรวมกันของบางอย่าง
Peter Taylor

@ PeterTaylor ขอบคุณมากสำหรับเคล็ดลับที่ยอดเยี่ยมเหล่านี้! มันค่อนข้างยากที่จะเข้าใจผู้ประกอบการ Golfscript ทั้งหมดและฉันมองข้ามสิ่งที่ตรงไปตรงมาสองอย่างนี้ โดยการใช้คำแนะนำสองข้อแรกเท่านั้นที่ฉันจัดการเพื่อทำให้รหัสสั้นลง 5 ตัวอักษร ฉันจะพยายามลบ$ข้อมูลอ้างอิงด้วย
Cristian Lupascu

1
นอกจากนี้การเรียกซ้ำไม่ได้เป็นสิ่งที่ GolfScript จริง ๆ ลองพลิกมันแล้ววนเป็นวงกลม ฉันสามารถลงไปที่ 19 ตัวอักษร (แม้ว่าจะไม่ได้ทดสอบรหัส) วิธีที่ คำแนะนำ: เหยียดฟังก์ชั่นgจากบทความวิกิพีเดียและการใช้งานและ, /
ปีเตอร์เทย์เลอร์

1
{,{\2$+\)%}*)\;}:f;ตรวจสอบให้แน่ใจว่าคุณเข้าใจว่าทำไมมันถึงได้ผล)
ปีเตอร์เทย์เลอร์

1
เคล็ดลับสุดท้ายหนึ่ง: แทนที่จะใช้ 2 ตัวอักษรเพื่อเข้าถึงkภายในลูปและอีก 2 เพื่อยกเลิกในตอนท้ายเราสามารถดึงมันเข้าไปด้านใน+เพื่อใช้เพื่อลดจำนวนอักขระได้ถึง 17 ตัว: {{@+\)%}+\,*)}:f;ฉันสงสัยว่าสามารถปรับปรุงได้
Peter Taylor





1

C, 88 ตัวอักษร

การจำลองไม่คำนวณสูตร
มีความยาวมากกว่าสูตร แต่สั้นกว่าแบบจำลอง C อื่น ๆ

j(n,k){
    int i=0,c=k,r=n,*p=calloc(n,8);
    for(;p[i=i%n+1]||--c?1:--r?p[i]=c=k:0;);
    return i;
}

หมายเหตุ:
1. จัดสรรหน่วยความจำและไม่เคยเผยแพร่
2. จัดสรรn*8แทนเพราะผมใช้n*4 p[n]สามารถจัดสรรได้(n+1)*4แต่มีตัวอักษรมากขึ้น


1

C ++, 166 ไบต์

แข็งแรงเล่นกอล์ฟ:

#include<iostream>
#include <list>
int j(int n,int k){if(n>1){return(j(n-1,k)+k-1)%n+1;}else{return 1;}}
int main(){intn,k;std::cin>>n>>k;std::cout<<j(n,k);return 0;}

Ungolfed:

#include<iostream>
#include <list>
int j(int n,int k){
    if (n > 1){
        return (j(n-1,k)+k-1)%n+1;
    } else {
        return 1;
    }
}
int main()
{
    int n, k;
    std::cin>>n>>k;
    std::cout<<j(n,k);
    return 0;
}

2
คุณสามารถบันทึกไบต์บนJฟังก์ชันโดยใช้ตัวดำเนินการประกอบ
Yytsi

intnในเวอร์ชันนักกอล์ฟของคุณจะไม่รวบรวม
Felipe Nardi Batista

คุณสามารถลบพื้นที่ใน#include <list>
Felipe Nardi Batista

1

J, 8 ไบต์

1&|.&.#:

       1&|.&.#: 10
    5

       1&|.&.#: 69
    11

        1&|.&.#: 123456
    115841

        1&|.&.#: 123245678901234567890x NB. x keeps input integral
    98917405212792722853

All credit to Roger Hui, co-inventor of J and all-round uber-genius
www.jsoftware.com for free j software across many platforms

Explanation
    (J works right-to-left)
     #:       convert input to binary
     &.       a&.b <=> perform b, perform a, perform reverse of b
     1&|.     rotate bitwise one bit left

So
    1&|.&.#: 10

    a. #:            convert input (10) TO binary -> 1 0 1 0
    b. 1&|.          rotate result 1 bit left -> 0 1 0 1
    c. due to the &. perform convert FROM binary -> 5 (answer)

1
มันควรจะใช้สองอินพุตหรือไม่?
Erik the Outgolfer





0

JavaScript (ECMAScript 5), 48 ไบต์

ใช้ ECMAScript 5 ตั้งแต่นั้นเป็นรุ่นล่าสุดของ JavaScript ในเวลาที่คำถามนี้ถูกถาม

function f(a,b){return a<2?1:(f(a-1,b)+b-1)%a+1}

รุ่น ES6 (ไม่แข่งขัน), 33 ไบต์

f=(a,b)=>a<2?1:(f(a-1,b)+b-1)%a+1

คำอธิบาย

ไม่มากที่จะพูดที่นี่ ฉันเพิ่งใช้ฟังก์ชั่นที่บทความ Wikipedia ให้ฉัน



0

8th , 82 ไบต์

รหัส

: j >r >r a:new ( a:push ) 1 r> loop ( r@ n:+ swap n:mod ) 0 a:reduce n:1+ rdrop ;

SED (Stack Effect Diagram) คือ:n k -- m

การใช้งานและคำอธิบาย

อัลกอริทึมใช้อาร์เรย์ของจำนวนเต็มดังนี้: ถ้าค่าของบุคคลคือ 5 ดังนั้นอาร์เรย์จะเป็น [1,2,3,4,5]

: j \ n k -- m
    >r                               \ save k
    >r a:new ( a:push ) 1 r> loop    \ make array[1:n]
    ( r@ n:+ swap n:mod ) 0 a:reduce \ translation of recursive formula with folding using an array with values ranging from 1 to n
    n:1+                             \ increment to move from 0-based to 1-based indexing
    rdrop                            \ clean r-stack
;

ok> 7 1 j . cr
7
ok> 7 2 j . cr
7
ok> 7 3 j . cr
4
ok> 7 11 j . cr
1
ok> 77 8 j . cr
1
ok> 123 12 j . cr
21

0

J , 24 ไบต์

1+1{1([:|/\+)/@,.1|.!.0#

ลองออนไลน์!

วิธีการวนซ้ำตามโซลูชันการเขียนโปรแกรมแบบไดนามิก

คำอธิบาย

1+1{1([:|/\+)/@,.1|.!.0#  Input: n (LHS), k (RHS)
                       #  Make n copies of k
                 1|.!.0   Shift left by 1 and fill with zero
    1          ,.         Interleave with 1
             /@           Reduce using
           +                Addition
        |/\                 Cumulative reduce using modulo
  1{                      Select value at index 1
1+                        Add 1

0

J , 19 ไบต์

1+(}:@|.^:({:@])i.)

ลองออนไลน์!

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

1+(}:@|.^:({:@])i.)   Left: k, Right: n
                i.    Generate [0..n-1]
        ^:            Repeat:
   }:@|.                Rotate left k items, and remove the last item
          ({:@])        n-1 (tail of [0..n-1]) times
1+                    Add one to make the result one-based


0

Japt 15 ไบต์

_é1-V Å}h[Uõ] Ì

ลองออนไลน์!

ไบต์สามารถบันทึกได้โดย0-indexing kแต่จริง ๆ แล้วมันไม่ใช่ดัชนีดังนั้นฉันจึงตัดสินใจ

คำอธิบาย:

         [Uõ]      :Starting with the array [1...n]
_      }h          :Repeat n-1 times:
 é1-V              : Rotate the array right 1-k times (i.e. rotate left k-1 times)
      Å            : Remove the new first element
              Ì    :Get the last value remaining


0

Powershell, 56 ไบต์

param($n,$k)if($n-lt2){1}else{((.\f($n-1)$k)+$k-1)%$n+1}

สิ่งสำคัญ! สคริปต์เรียกตัวเองซ้ำ ๆ ดังนั้นบันทึกสคริปต์เป็นf.ps1ไฟล์ในไดเรกทอรีปัจจุบัน นอกจากนี้คุณสามารถเรียกตัวแปรสคริปต์บล็อกแทนไฟล์สคริปต์ (ดูสคริปต์ทดสอบด้านล่าง) การโทรนั้นมีความยาวเท่ากัน

สคริปต์ทดสอบ:

$f = {

param($n,$k)if($n-lt2){1}else{((&$f($n-1)$k)+$k-1)%$n+1}

}

@(
    ,(7, 1, 7)
    ,(7, 2, 7)
    ,(7, 3, 4)
    ,(7, 11, 1)
    ,(77, 8, 1)
    ,(123,12, 21)
) | % {
    $n,$k,$expected = $_
    $result = &$f $n $k
    "$($result-eq$expected): $result"
}

เอาท์พุท:

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