ประปา ASCII


19

Intro

พิจารณากริดของตัวละครf A\/เช่น

f  f  f  
      A  
   A / \ 
\ /     A
    A \/ 
   /     
 \/         

ที่อยู่:

  • f หมายถึงก๊อกน้ำที่เทน้ำไหลลง
  • A แยกสายน้ำด้านบนออกเป็นสองส่วนครึ่งทางซ้ายและครึ่งทางที่ถูกต้อง
  • \ เลื่อนกระแสน้ำเหนือขึ้นไปทางขวาทีละหนึ่งหน่วย
  • / เลื่อนกระแสน้ำข้างบนไปทางซ้ายทีละหนึ่งหน่วย
  • การรวมกัน\/จะสร้างรางน้ำที่มีความจุไม่สิ้นสุดที่รวบรวมกระแสน้ำข้างบน
  • [space] เป็นพื้นที่ว่างเปล่ากว่าน้ำที่สามารถเคลื่อนที่ผ่านได้

จากนี้เราสามารถจินตนาการเส้นทางที่น้ำ ( *) จะใช้เมื่อมันออกมาจากก๊อกน้ำและตกลงไปในรางหรือออกจากพื้นที่กริด:

f  f  f    <-- first second and third faucets
*  * *A* 
* *A*/ \*
\*/ *  *A  <-- a '*' is not drawn to the right of this A because it would be out of the 9×7 bounds
 * *A*\/   <-- upper trough
 **/ *   
 \/  *     <-- lower trough

สมมติว่า 3 faucets ให้ปริมาณน้ำเท่ากันในแต่ละครั้งที่เราเห็น

  • น้ำแรกของ faucet ทั้งหมดไหลลงสู่รางล่าง
  • น้ำครึ่งหนึ่งของก๊อกน้ำที่สองไปที่รางล่างและอีกครึ่งหนึ่งจะถูกแยกระหว่างรางล่างและตกจากตะแกรง
  • หนึ่งในสี่ของก๊อกน้ำที่สามไปที่รางล่างหนึ่งในสี่ตกจากด้านล่างของตารางหนึ่งในสี่เข้าไปในรางบนและหนึ่งในสี่ตกจากตะแกรงไปทางขวา

จากนี้เราสามารถบอกได้ว่า(1 + 3/4 + 1/4 + 1/4) / 3 = 75%น้ำถูกจับโดยร่องน้ำและ(1/4 + 1/4 + 1/4) / 3 = 25%ตกจากตะแกรง

ความท้าทาย

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

ความท้าทาย 1
เขียนโปรแกรมที่ให้ส่วนของน้ำที่ไหลลงสู่รางสำหรับตารางที่กำหนด 0.75การส่งออกของตัวอย่างข้างต้นก็จะ

ความท้าทายที่ 2
เขียนโปรแกรมที่ให้กริดวาดเส้น*ในที่ที่น้ำไหลเหมือนที่ฉันได้ทำไปแล้ว คุณไม่ควรเขียนทับสิ่งใดนอกจากตัวอักษรเว้นวรรคและตารางไม่ควรเปลี่ยนขนาด ดังนั้นสำหรับสิ่งที่ชอบ

 f
/A

ไม่มีอะไรต้องทำตั้งแต่ถึงแม้ว่าน้ำจะไหลไปทางด้านใดด้านหนึ่งของ A แต่ก็ไม่สามารถลากไปทางซ้ายโดยไม่ต้องถอดออก/และไม่สามารถดึงไปทางขวาโดยไม่ทำให้ตาราง 2 × 2 ใหญ่ขึ้น

ความท้าทาย 3 (อัปเดต)
เขียนโปรแกรมที่ใช้จำนวนเต็มสองจำนวนที่ไม่เป็นลบจำนวน T ทั้งหมดและจำนวนเงินที่จะเก็บ K (T> = K) สร้างและวาดกริดด้วยหนึ่งอย่างfเช่นเมื่อก๊อกน้ำนั้นเทน้ำออกไปที T หน่วย K จะไหลลงสู่รางน้ำอย่างแน่นอน หากมันเป็นไปไม่ได้ที่จะทำเช่นนี้ในตาราง จำกัด สำหรับคู่ (T, K) ที่เฉพาะเจาะจงจากนั้นเอาท์พุท 'Impossible'

การชี้แจง (นำไปใช้กับความท้าทายทั้งหมด)

  • อินพุตสามารถผ่าน stdin หรือไฟล์หรือแม้แต่การเรียกใช้ฟังก์ชันบนการแทนค่าสตริงของกริด เพียงทำให้มันชัดเจนว่าจะใช้อินพุตที่แตกต่างกันอย่างไร
  • เอาต์พุตต้องไปที่ stdout
  • \AและA/และAAนอกจากนี้ยังมีร่องที่คุณคาดหวัง
  • กริด w โดย h จะเป็นรูปแบบสี่เหลี่ยมที่ดีเสมอของอักขระ w * h ที่ไม่นับบรรทัดใหม่ *จะไม่มีการเว้นวรรคต่อท้ายที่หายไปและการเกิดขึ้นของไม่มี
  • ขนาดกริดสามารถมีขนาดเล็กเท่ากับ 1 × 1 และมีขนาดใหญ่โดยพลการ (เหตุผลใหญ่ภายในเหตุผล int.maxValue หรือชอบเป็นข้อ จำกัด ที่ยอมรับได้เหมือนกันไปสำหรับ T และ K)
  • กระแสที่อยู่เหนือfกระแสที่ไหลผ่าน
  • Faucet สามารถอยู่ได้ทุกที่ไม่ใช่แค่อยู่แถวบนสุด
  • A หารปริมาณน้ำที่เทลงบนมันเสมอครึ่ง

หมายเหตุ:สิ่งที่ชอบ/Aและ//ใช้ได้อย่างสมบูรณ์ น้ำไม่ได้อย่างอิสระไหลระหว่างตัวละคร ( แต่สำหรับความท้าทาย 2 ไม่มีที่ว่างพอที่จะดึงมัน)

ดังนั้นในการตั้งค่า

ff

/A

fกระแสทางซ้ายเทลงมากระทบ/และเลื่อนไปทางซ้าย สิทธิfสตรีมเทลงฮิตAครึ่งไปทางขวาและซ้ายไปครึ่งระหว่างและA/

เช่น

 ff
 **
*/A*
** *
** *

3
+1 ความท้าทายที่ดี สำหรับความท้าทาย 3 ตารางที่ด้านบนจะไม่ใช่คำตอบที่ถูกต้องเพราะมันมี 3 fs
edc65

@ edc65 อ่าเยี่ยมมาก!
งานอดิเรกของ Calvin

2
คล้ายกันมาก: codegolf.stackexchange.com/questions/26059/…
Howard

2
สำหรับความท้าทายที่สองคุณต้องระบุวิธีการจัดการกับการป้อนข้อมูลเช่นถ้าน้ำตกอยู่บน/A Aสำหรับความท้าทายทั้งหมดจะเป็นการดีที่จะชี้แจงว่า\Aเป็นรางน้ำหรือไม่ สำหรับความท้าทายที่สามควรมี 3 หน่วยที่ตกอยู่บนข้อAสันนิษฐานที่จะแยกออก1.5 / 1.5(ดังนั้นการป้อนข้อมูลจึงเป็นจำนวนตรรกยะเพียงตัวเดียว) หรือเป็นเช่นนั้น2 / 1ในกรณีใดด้านใดที่ได้รับ2?
Peter Taylor

1
@ PeterTaylor ขอบคุณ ฉันได้ชี้แจงประเด็นเหล่านั้น ฉันเดาว่า T และ K น่าจะลอยได้ แต่ฉันจะทำให้มันเป็นจำนวนเต็มเพื่อความง่าย (แต่ถ้า T = 3 ตีAทั้งสองฝ่ายจะได้ 1.5 มันขึ้นอยู่กับ coder เพื่อให้แน่ใจว่าความแม่นยำของการลอยไม่ใช่ปัญหา)
งานอดิเรกของ Calvin

คำตอบ:


3

ความท้าทายทั้งหมด C # 690bytes (416bytes + 274bytes)

ความท้าทาย 1 & 2 C # 579 446 416bytes

นี่เป็นโปรแกรมที่สมบูรณ์ซึ่งควรทำสิ่งที่ท้าทาย 1 และ 2 เพียงเกี่ยวกับ มันอ่านบรรทัดของอินพุตจาก stdin จนกว่าจะได้รับบรรทัดว่าง มันพิมพ์ผลลัพธ์สำหรับ Challenge 2 และผลลัพธ์สำหรับ Challenge 1 ใช้คลาสทศนิยม. NET เพื่อหวังว่าจะหลีกเลี่ยงข้อผิดพลาดในการปัดเศษ

using C=System.Console;class P{static void Main(){decimal u,t=0,f=0;string c,z="";for(decimal[]n=null,o;(c=C.ReadLine())!="";z+='\n'){int s=c.Length,i=s,e;o=n;n=new decimal[s];for(o=o??n;i-->0;n[i]+=(e&2)*u/2){e=c[i]%13;u=o[i]/(e<1?2:1);if(e%8<1)if(i>0)if(c[i-1]%7<3)t+=u;else n[i-1]+=u;if(e<2)if(i<s-1)if(c[i+1]%2>0)t+=u;else n[i+1]+=u;if(e>9){u++;f++;}}for(;++i<s;)z+=c[i]<33&n[i]>0?'*':c[i];}C.WriteLine(z+t/f);}}

หักกอล์ฟ:

using C=System.Console;
class P
{
    static void Main()
    {
        decimal u,t=0,f=0;
        string c,z="";

        for(decimal[]n=null,o;(c=C.ReadLine())!="";z+='\n')
        {
            int s=c.Length,i=s,e;
            o=n;
            n=new decimal[s];
            for(o=o??n;i-->0;n[i]+=(e&2)*u/2)
            {
                e=c[i]%13;
                u=o[i]/(e<1?2:1);

                if(e%8<1)
                    if(i>0)
                        if(c[i-1]%7<3)t+=u;
                        else n[i-1]+=u;
                if(e<2)
                    if(i<s-1)
                        if(c[i+1]%2>0)t+=u;
                        else n[i+1]+=u;
                if(e>9)
                {
                    u++;
                    f++;
                }
            }
            for(;++i<s;)
                z+=c[i]<33&n[i]>0?'*':c[i];
        }

        C.WriteLine(z+t/f);
    }
}

ทดสอบการทำงาน (โดยไม่มีช่องว่างต่อท้ายซึ่งฉันสัญญาว่าจะมี):

f  f  f
      A
   A / \
\ /     A
    A \/
   /
 \/

f  f  f
*  * *A*
* *A*/ \*
\*/ *  *A
 * *A*\/
 **/ *
 \/  *
0.75

ท้า 3 C # 274bytes

นี่เป็นโปรแกรมที่สมบูรณ์ซึ่งควรจะเสร็จสิ้นการท้าทาย 3 ฉันจัดการเพื่อประหยัด 6bytes โดยการเขียนโปรแกรมแยกวิเคราะห์จำนวนเต็มของตัวเองเพื่ออ่านอินพุตมากกว่าSplitไอเอ็นจีReadLineและใช้long.Parse;

using C=System.Console;class P{static void Main(){long t=-1,f=t,k;for(;f<0;)for(f=t,t=0;(k=C.Read())>47;)t=t*10+k-48;var r="Impossible\n";for(k=t;k<t*f;)k*=2;if(f<1||(k/f)*f==k)for(r=" f \n";t>0&t<f;t-=(t/f)*f)r+=((t*=2)<f?" ":"A")+"A \n/ /\n";C.Write(r+(t<f?"":"AAA\n"));}}

หักกอล์ฟ:

using C=System.Console;
class P
{
    static void Main()
    {
        long t=-1,f=t,k;
        for(;f<0;)
            for(f=t,t=0;(k=C.Read())>47;)
                t=t*10+k-48;

        var r="Impossible\n";
        for(k=t;k<t*f;)
            k*=2;
        if(f<1||(k/f)*f==k)
            for(r=" f \n";t>0&t<f;t-=(t/f)*f)
                r+=((t*=2)<f?" ":"A")+"A \n/ /\n";
        C.Write(r+(t<f?"":"AAA\n"));
    }
}

ทดสอบการทำงาน (อีกครั้งโดยไม่มีช่องว่างต่อท้ายซึ่งฉันสัญญาว่าจะมี):

32 17
 f
AA
/ /
 A
/ /
 A
/ /
 A
/ /
AA
/ /

3

ก่อนอื่นฉันมีคำถามเกี่ยวกับความท้าทาย เนื่องจากฉันไม่มีชื่อเสียงพอที่จะแสดงความคิดเห็นเกี่ยวกับคำถามฉันจึงเขียนมันที่นี่:

  • พฤติกรรมของ/A(น้ำไหลบน A), //(น้ำไหลทางด้านขวา) และการเปลี่ยนแปลงของหลักการนี้คืออะไร? น้ำไหลไปที่ "จุดอิสระ" แรกที่ด้านข้างหรือไม่หรือ "ไหล" ด้านล่าง "เพื่อนบ้าน?

แค่ลองง่ายๆก็สามารถ waaaaay ประยุกต์ (ซึ่งฉันจะทำในภายหลังโดยการแก้ไขโพสต์นี้)

แก้ไข:รุ่นที่สองมีขนาดเล็กลงเล็กน้อย ฉันไปหาวิธีที่แตกต่าง: แทนที่จะมองหาแต่ละเซลล์เพื่อตรวจสอบสิ่งที่มาจากด้านบนและด้านข้างฉันเริ่มจาก faucets และ "flow" ลงด้านล่างด้วยการเรียกซ้ำ

Javascript, 226 ไบต์ (ความท้าทาย 1)

function f(c){function h(b,a,d,e){b<c.length&&0<=a&&a<c[0].length&&("\\"==c[b][a]?"/"==e||"A"==e?g+=d:h(b,a+1,d,"\\"):"/"==c[b][a]?"\\"==e||"A"==e?g+=d:h(b,a-1,d,"/"):"A"==c[b][a]?"A"==e||"\\"==e||"/"==e?g+=d:(h(b,a-1,d/2,"A"),h(b,a+1,d/2,"A")):h(b+1,a,d,c[b][a]))}for(var g=0,m=0,k=0;k<c.length;k++)for(var l=0;l<c[k].length;l++)"f"==c[k][l]&&(h(k+1,l,1),m++);alert(g/m)};

Javascript, 204 ไบต์ (ความท้าทาย 2)

function f(c){function e(b,a,d){b<c.length&&0<=a&&a<c[0].length&&("\\"==c[b][a]?"/"!=d&&"A"!=d&&e(b,a+1,"\\"):"/"==c[b][a]?"\\"!=d&&"A"!=d&&e(b,a-1,"/"):"A"==c[b][a]?"A"!=d&&"\\"!=d&&"/"!=d&&(e(b,a-1,"A"),e(b,a+1,"A")):(" "==c[b][a]&&(c[b][a]="*"),e(b+1,a,c[b][a])))}for(var g=0;g<c.length;g++)for(var h=0;h<c[g].length;h++)"f"==c[g][h]&&e(g+1,h)};

Javascript, 238 ไบต์ (Challenge 1 + 2)

function f(c){function h(b,a,d,e){b<c.length&&0<=a&&a<c[0].length&&("\\"==c[b][a]?"/"==e||"A"==e?g+=d:h(b,a+1,d,"\\"):"/"==c[b][a]?"\\"==e||"A"==e?g+=d:h(b,a-1,d,"/"):"A"==c[b][a]?"A"==e||"\\"==e||"/"==e?g+=d:(h(b,a-1,d/2,"A"),h(b,a+1,d/2,"A")):(" "==c[b][a]&&(c[b][a]="*"),h(b+1,a,d,c[b][a])))}for(var g=0,m=0,k=0;k<c.length;k++)for(var l=0;l<c[k].length;l++)"f"==c[k][l]&&(h(k+1,l,1),m++);alert(g/m)};

วิธีใช้

จัดทำแผนที่สองมิติของแผนที่ นี่คือตัวอย่างที่ให้ไว้ในคำถาม:

var input = [["f"," "," ","f"," "," ","f"," "," "],[" "," "," "," "," "," ","A"," "," "],[" "," "," ","A"," ","/"," ","\\"," "],["\\"," ","/"," "," "," "," "," ","A"],[" "," "," "," ","A"," ","\\","/"," "],[" "," "," ","/"," "," "," "," "," "],[" ","\\","/"," "," "," "," "," "," "]];
f(input);

เอาท์พุต

ความท้าทายที่ 1: มันจะสร้างกล่องโต้ตอบ (การแจ้งเตือน) พร้อมผลลัพธ์ (0.75 สำหรับตัวอย่างด้านบน)

Challenge 2: มันจะแก้ไขแผนที่โดยตรง ฉันควรพิมพ์หรือไม่ ถ้าเป็นเช่นนั้น console.log เป็นที่ยอมรับ? เป็นผลลัพธ์ที่ถูกต้อง?

ความท้าทาย 1 + 2: ทั้งสองอย่างรวมกันอย่างเห็นได้ชัด ...


น้ำไหลไปมาระหว่างตัวละครราวกับว่ามันกำลังกอดเส้นของAหรือทับ ฉันชี้แจงว่าในคำถาม
งานอดิเรกของ Calvin

คำถามระบุOutput must go to stdout.
user80551

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

1
user80551 ขอบคุณฉันไม่รู้ว่าทำไมมันหลุดออกมาจากใจของฉัน ฉันจะอัปเดตรหัสของฉันโดยเร็วที่สุด @tomsmeding ใช่มันใช้งานได้สำหรับคำตอบของความท้าทาย 1. แต่สำหรับความท้าทาย 2 ฉันกำลังแก้ไขอินพุตโดยตรงและคุณไม่สามารถแก้ไขอักขระในสตริงโดยใช้ str [i] ดังนั้นการใช้อาร์เรย์
รีเฟรช

2

Python 3, 186 ไบต์ (Challenge 3)

ผมเอาความคิดสำหรับตารางจากคำตอบของ VisualMelon ฟังก์ชั่นควรพิมพ์กริดที่ถูกต้องไปยัง stdout สำหรับ T และ K ขนาดใหญ่โดยพลการหากเป็นไปได้ (แน่นอนขนาดกริด)

from fractions import*
def c(T,K):
 p=print;g=gcd(T,K);K//=g;T//=g
 if T&(T-1):p('Impossible')
 else:
  p(' f ')
  while T-1:
   T//=2;p('A/'[K<T]+'A \n///')
   if K>=T:K-=T
  p('AAA'*K)

วิธีใช้

เรียกใช้cฟังก์ชันด้วยยอดรวมและจำนวนเงินเพื่อเก็บเป็นอาร์กิวเมนต์

>>> c(24, 9)
 f 
/A 
///
AA 
///
AA 
///

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