พิมพ์ ascii Spiral ในหน่วยความจำ O (log n)


13

คุณสามารถเขียนโปรแกรมหรือฟังก์ชั่นที่รับจำนวนเต็มคี่บวก nที่ซึ่งn >= 3เป็นฟังก์ชันอาร์กิวเมนต์อาร์กิวเมนต์บรรทัดคำสั่งหรือบน STDIN (หรือเทียบเท่ากับระบบของคุณ) และพิมพ์ไปยัง STDOUT (หรือเทียบเท่าระบบ) เกลียว ASCII ที่หมุนเข้าด้านในตามเข็มนาฬิกาโดยที่ขอบด้านบนมีความnยาวอักขระอย่างแน่นอน ขอบด้านขวาแรกควรมีความn+1ยาวอักขระ ตัวอย่างเช่น

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

11

เอาท์พุท:

***********
          *
********* *
*       * *
* ***** * *
* *   * * *
* * * * * *
* * *** * *
* *     * *
* ******* *
*         *
***********

จับ:

  • โปรแกรมของคุณต้องใช้ไม่เกินหน่วยความจำO(log n)
  • โปรแกรมของคุณอาจพิมพ์อักขระ*(ASCII 42), (ASCII 32), <CR>(ASCII 13) และ<LF>(ASCII 10)
  • โปรแกรมของคุณต้องพิมพ์สตริงไม่ใช่ส่งคืนจากฟังก์ชัน
  • ข้อ จำกัด Big-O มีเฉพาะในหน่วยความจำเท่านั้นไม่มีข้อ จำกัด ในการใช้งานจริง
  • บรรทัดใหม่ต่อท้ายเป็นตัวเลือก
  • หากภาษาของคุณไม่รองรับประเภทจำนวนเต็มขนาดใหญ่คุณไม่จำเป็นต้องสนับสนุนสูงกว่าที่รองรับ แต่คุณอาจไม่ใช้สิ่งนี้เป็นเคล็ดลับในการพูดว่า "โอ้ดีฉันไม่ต้องสนับสนุนข้างบน X ดังนั้นฉัน สามารถสร้างอาร์เรย์ขนาดใหญ่ได้ทุกครั้ง "

ช่องโหว่มาตรฐานถูกแบนเช่นเคย


2
ฉันไม่เชื่อว่าเป็นไปได้ หนึ่งไม่สามารถเก็บอินพุตnในหน่วยความจำ O (1)
xnor

@xnor "O (1) ถือว่ามีการใช้หน่วยความจำคงที่ดังนั้นจำนวนของอินพุตนั้นไม่สำคัญ" - หากอินพุต n พอดีกับจำนวนเต็มดังนั้นฉันแน่ใจว่ามันสามารถถูกเข้ารหัสในการใช้หน่วยความจำคงที่ได้
André

1
การจัดเก็บอินพุตnใช้เวลาlog nบิต เช่นเดียวกับที่nมีขนาดใหญ่ขึ้นพื้นที่จัดเก็บจึงจำเป็นต้องใช้เช่นกัน คุณอาจจะบอกว่าทำสิ่งนี้ด้วยตัวแปรที่มีจำนวน จำกัด หรือไม่?
xnor

หรือมิฉะนั้นจะมีการ จำกัดnหรือไม่
Sp3000

ฉันคิดว่าเขาบอกว่าคุณไม่สามารถจัดเก็บผลลัพธ์ทั้งหมดในคราวเดียวจากนั้นพิมพ์มันทั้งหมดในครั้งเดียวเพราะมันจะใหญ่ขึ้น คุณอาจต้องพิมพ์ซ้ำซ้ำ
จาค็อบ

คำตอบ:


9

C, 125 121 ไบต์

แข็งแรงเล่นกอล์ฟรุ่นkนี้มีตัวแปรไม่มี ตัวแปรkนี้ใช้ในเวอร์ชันที่ไม่ดีเพื่อช่วยให้อ่านง่าย นอกจากนี้ยังforมีการจัดเงื่อนไขแบบวนซ้ำและ{}ลบชุดที่ไม่จำเป็นหนึ่งชุด ชุดอื่น{}สามารถลบออกได้โดยการย้ายputs("")ภายในวงเล็บของjลูปในตำแหน่งเริ่มต้น แต่นี่หมายถึงการขึ้นบรรทัดใหม่ที่จุดเริ่มต้นของเอาต์พุตดังนั้นฉันจึงไม่ได้ทำมัน

f(n){int i,j;n/=2;for(i=-n-2;i++-n-1;){if(i){for(j=-n-1;j++-n;)putchar(32+10*(n+(j*j<i*i?i:j+(i!=j|i>0))&1));puts("");}}}

พิมพ์หน้าnกว้างตามn+1เกลียวสูงเช่นตัวอย่าง

คำอธิบาย

โดยทั่วไปฉันลดลงครึ่งหนึ่งค่าของn(ปัดเศษลง) และเรียกใช้สอง loops: หนึ่งนอกiจาก-n/2-1จะn/2+1พิมพ์แถว ( i=0ถูกระงับเราจึงได้รับn+1แถว) และหนึ่งภายในjจาก ( -n/2การn/2ที่เราใช้ในการพิมพ์ตัวอักษร.) expression & 1ในการพิมพ์ลาย และเงื่อนไขj*j<i*iในการตัดสินใจว่าจะพิมพ์แถบแนวตั้งหรือแนวนอน (แนวตั้งที่ด้านข้างที่iมีขนาดใหญ่กว่าและแนวนอนที่ด้านบนและล่าง) +nจำเป็นต้องมีการปรับเพื่อช่วยในการยกเลิกที่ถูกต้องขึ้นอยู่กับว่าn/2เป็นคี่หรือ แม้

kเป็นปกติที่ 1 และยังมีการปรับสำหรับความจริงที่ว่าค่าแน่นอนของiช่วงตั้งแต่ 1 ถึงn/2+1ขณะที่ค่าแน่นอนของjช่วงตั้งแต่ 0 n/2ถึง ถ้าkเป็น 1 เสมอเราจะได้สี่เหลี่ยมศูนย์กลาง แต่มันกลับเป็น 0 เมื่อi==j&i<=0เซลล์ในแนวทแยงมุมกลับด้านทำให้เกิดเกลียว

ungolfed ในโปรแกรมทดสอบ

f(n){
  int i,j,k;
  n/=2;
  for(i=-n-1;i<=n+1;i++){
    if(i){
       for(j=-n;j<=n;j++){
           k=i!=j|i>0;
           putchar(32+10*(n+(j*j<i*i?i:k+j)&1));
         }
       puts("");
     }
  }
} 

int m;
main(){
  scanf("%d",&m);
  f(m);
}

เอาท์พุต

11
***********
          *
********* *
*       * *
* ***** * *
* *   * * *
* * * * * *
* * *** * *
* *     * *
* ******* *
*         *
***********

9
*********
        *
******* *
*     * *
* *** * *
* * * * *
* *   * *
* ***** *
*       *
*********

3
***
  *
* *
***

1
*
*

เอาชนะฉันนิดหน่อย ... +1 นี่มันสั้นมาก!
sudo rm -rf slash


7

C, 118 ไบต์

m,p,x,y,d;f(n){for(m=n++/2;p<n*n;x=p%n-m,y=p++/n-m,d=y==x+1&x<0,y-=y>0,d+=x*x>y*y?x:y,putchar(x>m?10:(d+m)%2?32:42));}

รหัสก่อนการเล่นกอล์ฟครั้งสุดท้าย:

#include <stdio.h>

int m, p, x, y, d;

int f(int n) {
    for (m = n++ / 2; p < n * n; ) {
        x = p % n - m;
        y = p++ / n - m;
        d = y == x + 1 && x < 0;
        y -= y > 0;
        d += x * x > y * y ? x : y;
        if (x > m) {
            putchar(10);
        } else if ((d + m) % 2) {
            putchar(32);
        } else {
            putchar(42);
        }
    }

    return 0;
}

การสังเกตที่สำคัญคือลวดลายนั้นเกือบจะเป็นชุดของกำลังสองที่ศูนย์กลาง ด้วยริ้วรอยเล็กน้อย:

  • y-size ใหญ่กว่า x-size อย่างใดอย่างหนึ่ง สิ่งนี้ถูกแก้ไขโดยการลบ 1 จาก y สำหรับครึ่งล่างซึ่งจะเป็นการซ้ำแถวกลาง
  • ในการแปลงสี่เหลี่ยมเป็นเกลียวให้หมุนพิกเซลตามy = x + 1แนวทแยงมุมไปทางด้านหลังตรงกลางของรูปร่าง

สำหรับส่วนที่เหลือโค้ดจะวนซ้ำทุกตำแหน่งคำนวณระยะทาง Chebyshev จากกึ่งกลางของแต่ละตำแหน่งและเปล่งหนึ่งในสองตัวละครขึ้นอยู่กับระยะทางที่เท่ากันหรือคี่ และเปล่งบรรทัดใหม่สำหรับตำแหน่งสุดท้ายของแต่ละบรรทัด

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


คำตอบที่ดี แต่ที่คุณไม่ได้เริ่มต้นpผมคิดว่าคุณตกเหม็นของmeta.codegolf.stackexchange.com/q/4939/15599 ฉันไม่แน่ใจเกี่ยวกับการประกาศตัวแปรทั่วโลกเมื่อส่งฟังก์ชั่น เห็นได้ชัดว่าคำตอบของฉันจะสั้นลง 4 ไบต์ถ้าฉันทำสิ่งนี้ ฉันเริ่มเมตาโพสต์แล้วmeta.codegolf.stackexchange.com/q/5532/15599
เลเวลริเวอร์เซนต์

ใช่ฉันคิดว่าฉันน่าจะเริ่มต้นpได้
Reto Koradi

3

C ++, 926 ไบต์

#include<iostream>
#include<string>
#include<math.h>
#define S string
using namespace std;S N(S x,int y){S z="";for(int q=0;q<y;q++){z+=x;}return z;}int main(){int n=0,t=0,g=0,fi=1;cin>>n;int t1[]={0,0,n,0};int t2[]={0,n-2,n-2,1};for(int k=0;k<n+1;k++){if((k>(n-2)/2)&&(k<(n+5)/2)){if(g==0){S d,e;if(!((n+1)%4)){cout<<N("* ",t2[0])<<"  *"<<N(" *",t2[0])<<endl<<N("* ",(n+1)/2)<<endl<<N("* ",t2[0])<<"***"<<N(" *",t2[0])<<endl;t2[2]=n-8-(n-11);t1[2]=n-4-(n-11);t1[0]--;t2[3]--;t1[3]-=2;}else{cout<<N("* ",t1[0])<<"***"<<N(" *",t2[0])<<endl<<N("* ",(n+1)/2)<<endl<<N("* ",t1[0])<<"*  "<<N(" *",t2[0])<<endl;t2[0]--;t1[2]+=2;t2[2]+=6;t1[3]--;t2[1]-=2;t2[3]-=2;}fi=0;}g=5;}else{t=1-t;int*tR;tR=t?t1:t2;cout<<N("* ",tR[0])<<N(t?"*":" ",tR[2])<<N(" *",tR[3])<<endl;if(fi){if(t){t1[0]+=k==0?0:1;t1[2]-=k==0?2:4;t1[3]++;}else{t2[0]++;t2[2]-=4;t2[3]++;}}else{if(t){t1[0]--;t1[2]+=4;t1[3]--;}else{t2[0]--;t2[2]+=4;t2[3]--;}}}}return 0;}

นี่ไม่ใช่ความสง่างาม แต่มันไม่ได้ใช้หน่วยความจำมากสำหรับ n ขนาดใหญ่ ยิ่งกว่านั้นมี (เกือบแน่นอน) ประมาณ 20 ตัวอักษรที่สามารถตีกอล์ฟต่อไปได้ แต่ฉันไม่สามารถทนดูได้อีกต่อไป

คำอธิบายสั้น ๆ :

สิ่งนี้จะแยกเส้นในเกลียวออกเป็นสองประเภท: อันที่มี ****** อยู่ตรงกลางและอีกอันที่มี \ s \ s \ s \ s \ s อยู่ตรงกลาง จากนั้นเป็นที่ชัดเจนว่าแต่ละบรรทัดประกอบด้วย "*" s หลายอันตรงกลางและบางส่วน "*" การพิจารณาว่าแต่ละสิ่งมีความเรียบง่ายเพียงใดหากคุณดูลวดลายเป็นเวลานานพอ สิ่งที่ยุ่งยากคือการพิมพ์จุดศูนย์กลางของเกลียวซึ่งโดยทั่วไปฉันเขียนโค้ดยากโดยใช้เงื่อนไข สิ่งนี้กลายเป็นประโยชน์เพราะ *** และ \ s \ s \ s สลับบรรทัดเป็นเลขคี่ / คู่

แบบทดสอบ:

อินพุต: 55 (ฉันคิดว่าสิ่งที่ยิ่งใหญ่ดูดีที่สุด)

เอาท์พุท:

************************************************** *****
                                                      * * * *
************************************************** *** *
* * *
* *************************************************** * *
* * * * *
* * *********************************************** * * *
* * * * * * *
* * * ******************************************** * * * *
* * * * * * * *
* * * * ************************************** * * * * *
* * * * * * * * * * *
* * * * * ********************************* * * * * * *
* * * * * * * * * * * * *
* * * * * * ***************************** * * * * * * *
* * * * * * * * * * * * * * *
* * * * * * * ************************* * * * * * * * *
* * * * * * * * * * * * * * * * * *
* * * * * * * * ********************* * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * *
* * * * * * * * ***** ***************** * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * ************* * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * ********* * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * ***** * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - {- โปรแกรมของฉันเพิ่มพื้นที่ที่นี่ btw
* * * * * * * * * * * * * * *** * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * ******* * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * *********** * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * *************** * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * ********************* * * * * * * * * * *
* * * * * * * * * * * * * * * * * * *
* * * * * * * * *********************** * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * *************************** * * * * * * *
* * * * * * * * * * * * * *
* * * * * * ******************************* * * * * * *
* * * * * * * * * * * *
* * * * * ************************************ * * * * *
* * * * * * * * *
* * * * **************************************** * * * *
* * * * * * * *
* * * ********************************************* * * *
* * * * * *
* * ************************************************** * * * *
* * * *
* *************************************************** ** *
* *
************************************************** *****

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

เอาท์พุท:

***
  * * * *
* * 
***

หมายเหตุ: ฉันไม่ใช่นักวิทยาศาสตร์คอมพิวเตอร์ / นักเรียน CS และฉันไม่รู้วิธีพิสูจน์ว่าใช้หน่วยความจำ O (log n) ฉันทำได้เฉพาะสิ่งที่ต้องทำตามลิงก์ในคำถาม ฉันจะขอบคุณถ้ามีใครสามารถยืนยัน / ปฏิเสธถ้าคำตอบนี้ถูกต้อง ตรรกะของฉันสำหรับความถูกต้องของคำตอบนี้คือมันไม่เคยเก็บตัวแปรขนาดใด ๆ ตาม n ยกเว้นอินพุตเอง แทนการวนซ้ำที่รัน n คูณคำนวณค่าจำนวนเต็มแทน n มีค่าจำนวนเดียวกันโดยไม่คำนึงถึงอินพุต

Note2: วิธีนี้ใช้ไม่ได้กับ n = 1 เนื่องจากวิธีการจัดการกับส่วนกลางของฉัน สิ่งนี้จะแก้ไขได้ง่ายด้วยเงื่อนไขดังนั้นหากใครก็ตามที่มีคำตอบของฉันไม่กี่ตัวละครฉันจะแก้ไข;)

เล่นกับมันใน ideone


ฉันเชื่อว่ามันใช้ได้แม้ว่ารหัส C ++ ที่มากในบรรทัดเดียวนั้นเป็นประเภทที่ต้องอ่าน ;) ความเข้าใจของคุณถูกต้อง nคุณไม่สามารถใช้หน่วยความจำที่มีขนาดที่ขึ้นอยู่กับ ตัวอย่างทั่วไปที่ไม่เป็นไปตามข้อกำหนดคือสตริง / บัฟเฟอร์ / อาร์เรย์บางชนิดที่เก็บสายเอาท์พุททั้งหมด
Reto Koradi

เนื่องจากนี่เป็นเพียงคำตอบเดียวฉันได้ปรับคำถามเป็นไม่ต้องการการจัดการn=1เนื่องจากฉันไม่ได้พิจารณาตัวเรือนพิเศษที่น่าสนใจ
durron597

3

Haskell, 151 ไบต์

(#)=mod
f n=[[if y<= -(abs$x+1)||y>abs x then r$y#2/=n#2 else r$x#2==n#2|x<-[-n..n]]|y<-[-n-1..n+1],y/=0]
r b|b='*'|1<2=' '
p=putStr.unlines.f.(`div`2)

ตัวอย่างการใช้งาน:

*Main> p 9
*********
        *
******* *
*     * *
* *** * *
* * * * *
* *   * *
* ***** *
*       *
*********

*Main> p 11
***********
          *
********* *
*       * *
* ***** * *
* *   * * *
* * * * * *
* * *** * *
* *     * *
* ******* *
*         *
***********

ด้วยความเกียจคร้านของ Haskell สิ่งนี้จะทำงานภายในหน่วยความจำคงที่ โดยจะใช้วิธีการที่เห็นได้ชัดคือวนลูปyและxเลือกระหว่าง*และขึ้นอยู่กับ

  • ถ้าตำแหน่งปัจจุบันสูงกว่าหรือต่ำกว่าเส้นทแยงมุม
  • xรับผิดชอบ yเป็นคู่หรือคี่
  • n/2 เป็นคู่หรือคี่

2

เสียงกระเพื่อมสามัญ - 346

(lambda(n &aux(d 0))(tagbody $ #6=(#7=dotimes(i n)#4=(princ"*"))#2=(#7#(i d)#5=(princ" ")#4#)#3=(terpri)#1=(#7#(i d)#4##5#)(when(> n 0)(#7#(i(1- n))#5#)#4#)#2##3#(when(> n 3)#1##4##4#(incf d)(decf n 4)(go $))(go /)@(decf d)(incf n 4)(when(> n 3)#2##5##4##3#)/ #1#(when(> n 0)#4#)(when(> n 1)(#7#(i(- n 2))#5#)#4#)#2##3##1##6#(when(> d 0)(go @))))

โซลูชันซ้ำกับการใช้หน่วยความจำอย่างต่อเนื่อง ข้างต้นทำให้การใช้งานหนัก#n=และ#n#ตัวแปรของเครื่องอ่าน แม้ว่าจะมีวิธีการเพิ่มเติมโดยตรงที่นี่ฉันเริ่มต้นด้วยฟังก์ชั่นซ้ำและแก้ไขเพื่อจำลองการสอบถามซ้ำด้วยgotoคำสั่ง: นี่อาจจะไม่สามารถอ่านได้

เอาท์พุทสำหรับค่าเข้าทั้งหมด 0-59

เวอร์ชันเรียกซ้ำดั้งเดิมพร้อมด้วยข้อมูลการดีบัก

(หมายเหตุ: terpriหมายถึงnewline)

(defun spiral (n &optional (d 0) )
  (flet ((prefix ()
           (format t "~4d~4d | " n d)
           (dotimes (i d)
             (princ "a ")))
         (postfix ()
           (dotimes (i d)
             (princ " b"))))
    (when (= d 0) (prefix))
    (dotimes (i n) (princ "c"))
    (postfix)
    (terpri)

    (prefix)
    (when (> n 0)
      (dotimes (i (1- n)) (princ " "))
      (princ "d"))
    (postfix)
    (terpri)

    (when (> n 3)
      (prefix)
      (princ "**")
      (spiral (- n 4) (1+ d))
      (postfix)
      (princ " f")
      (terpri))

    (prefix)
    (when (> n 0)
      (princ "g"))

    (when (> n 1)
      (dotimes (i (- n 2)) (princ " "))
      (princ "h"))
    (postfix)
    (terpri)

    (prefix)
    (dotimes (i n) (princ "i"))
    ))

ตัวอย่างเช่น:

(spiral 8)

   8   0 | cccccccc
   8   0 |        d
   8   0 | **cccc b
   4   1 | a    d b
   4   1 | a ** b b
   0   2 | a a  b b
   0   2 | a a  b b
   0   2 | a a  b f
   4   1 | a g  h b
   4   1 | a iiii f
   8   0 | g      h
   8   0 | iiiiiiii

ดูเพิ่มเติมที่การวางนี้พร้อมผลลัพธ์ทั้งหมดตั้งแต่ 0 ถึง 59 (ไม่เหมือนข้างบนอันนี้จะละเอียดมากขึ้น)

เวอร์ชันซ้ำแล้วซ้ำกับข้อมูลการดีบัก

(defun spiral (n &aux (d 0) )
  (flet ((prefix ()
           (format t "~4d~4d | " n d)
           (dotimes (i d)
             (princ "a ")))
         (postfix ()
           (dotimes (i d)
             (princ " b"))))
    (tagbody
     step-in
       (when (= d 0) (prefix))
       (dotimes (i n) (princ "c"))
       (postfix)
       (terpri)

       (prefix)
       (when (> n 0)
         (dotimes (i (1- n)) (princ " "))
         (princ "d"))
       (postfix)
       (terpri)

       (when (> n 3)
         (prefix)
         (princ "**")

         (incf d)
         (decf n 4)
         (go step-in))

       (go skip)

     step-out
       (decf d)
       (incf n 4)
       (when (> n 3)
         (postfix)
         (princ " f")
         (terpri))

     skip
       (prefix)
       (when (> n 0)
         (princ "g"))

       (when (> n 1)
         (dotimes (i (- n 2)) (princ " "))
         (princ "h"))
       (postfix)
       (terpri)

       (prefix)
       (dotimes (i n) (princ "i"))
       (when(> d 0)(go step-out)))))

คุณช่วยอธิบายได้ว่าสิ่งนี้ตรงตามข้อ จำกัด ของหน่วยความจำหรือไม่? ฉันเห็นจุดเรียกซ้ำเดียวซึ่งดี แต่คุณสามารถเพิ่มรายละเอียดได้อีกเล็กน้อยหรือไม่
durron597

@ durron597 ใช่ฉันกำลังทำสิ่งนี้อยู่ นี่คือ O (n) ในปัจจุบันเนื่องจากเราเรียกใช้ฟังก์ชันซ้ำตามสัดส่วนเวลาnและ call stack เติบโตตามลำดับ แต่ในกรณีนี้เราสามารถจำลองการเรียกซ้ำด้วยสองลูป: หนึ่งที่มีการnลดลงและdเพิ่มขึ้น (จนถึง n <= 3 ) และอีกอันที่dลดลงเหลือศูนย์ ตอนนี้ฉันไม่มีเวลามากพอที่จะทำงานนี้ แต่ฉันจะพยายามอัปเดตคำตอบตามนั้น Btw มีวิธีการพิมพ์เกลียวโดยตรงมากขึ้น แต่มันก็สนุกดีที่พยายามกำหนดมันซ้ำ ๆ
coredump

2

CJam, 72 ไบต์

li_2/:M;)__*{1$mdM-\M-_2$)=2$0<*@_*@_0>-_*e>mQ_M>2*@@+M+2%+'#S+N+N+=o}/;

นี่เป็นการแปลงโดยตรงจากโซลูชัน C ของฉันเป็น CJam ไม่สั้นอย่างที่คุณคาดหวังจากโซลูชัน CJam แต่อันนี้จริง ๆ ทนทุกข์ทรมานจากข้อ จำกัด ของหน่วยความจำ ประโยชน์ทั่วไปของการสร้างผลลัพธ์บนสแต็กที่ถูกเททิ้งโดยอัตโนมัติในตอนท้ายและการใช้งานการดำเนินการ list / string แฟนซีทั้งหมดล้วนออกไปนอกหน้าต่าง สิ่งนี้จะสร้างและส่งออกโซลูชันทีละตัวอักษร สแต็กมีจำนวนเต็มเพียงไม่กี่ตัวที่รันไทม์และไม่มีข้อมูลในตอนท้าย

แม้ว่ามันจะไม่ได้เป็นภาษาที่ใช้ในการตีกอล์ฟ แต่ก็ยังสั้นกว่ารหัส C เพียงเล็กน้อยเนื่องจากสัญกรณ์มีขนาดกะทัดรัดกว่า

คำอธิบาย:

li    Get input n.
_2/   Calculate n/2.
:M;   Store it in variable M
)__*  Calculate (n+1)*(n+1), which is the total number of output characters.
      Also keep a copy of n+1 on the stack.
{     Start loop over output character positions.
  1$md  Calculate divmod of position with n+1. This gives y and x of position.
  M-    Subtract M from x.
  \M-   Subtract M from y.
  _     Copy y.
  2$)   Calculate x+1.
  =     Check if y == x+1
  2$0<  Check if x < 0.
  *     Multiply the two check results. This is the result of the flip
        condition for the top-left diagonal to turn the rectangles into a spiral.
  @_*   Calculate x*x.
  @_    Get y to top of stack, and copy it.
  0>-   Subtract 1 from y if it is in the bottom half.
  _*    Calculate y*y.
  e>    Take maximum of x*x and y*y...
  mQ    ... and calculate the square root. This is the absolute value of the
        larger of the two.
  _M>   Check if the value is greater M, which means that this is the
        position of a line end.
  2*    Multiply by 2 so that we can add another condition to it later.
  @     Get result of diagonal flip condition to the stack top.
  @     Get max(x,y) to the top.
  +M+   Add the two, and add M to the whole thing. This value being even/odd
        determines if the output is a # or a space.
  2%    Check if value is odd.
  +     Add to line end condition to get a single ternary condition result.
  '#S+N+N+
        Build string "# \n\n".
  =     Use the condition result to pick the output character out of the string.
  o     Output the character.
}/    End loop over output characters.
;     Pop n+1 value off stack, to leave it empty.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.