Nhà máy nước ASCII


19

Giới thiệu

Hãy xem xét một lưới các ký tự f A\/như

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

Ở đâu:

  • f đại diện cho một vòi đổ một dòng nước xuống
  • A phân chia dòng nước ở trên để chính xác một nửa đi bên trái và chính xác một nửa đi bên phải
  • \ chuyển dòng nước bên trên sang phải một đơn vị
  • / chuyển dòng nước bên trên sang bên trái một đơn vị
  • sự kết hợp \/tạo ra một máng có khả năng vô hạn thu thập các dòng nước bên trên nó
  • [space] là không gian trống hơn nước có thể di chuyển qua

Từ đó, chúng ta có thể tưởng tượng con đường mà nước ( *) sẽ đi khi ra khỏi vòi và rơi vào máng hoặc ra khỏi khu vực lưới:

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

Giả sử 3 vòi sản lượng cùng một lượng nước tại một thời điểm chúng ta có thể thấy rằng

  • Tất cả nước của vòi đầu tiên chảy xuống máng dưới.
  • Một nửa lượng nước của vòi thứ hai chảy xuống máng dưới và nửa còn lại bị tách ra giữa máng dưới và rơi ra khỏi lưới điện.
  • Một phần tư nước của vòi thứ ba chảy xuống máng dưới, một phần tư rơi xuống đáy lưới, một phần tư đi vào máng trên và một phần tư rơi khỏi lưới bên phải.

Từ đó, chúng ta có thể biết rằng (1 + 3/4 + 1/4 + 1/4) / 3 = 75%nước bị các máng bắt và (1/4 + 1/4 + 1/4) / 3 = 25%rơi ra khỏi lưới điện.

Thử thách

Bạn có thể hoàn thành bất kỳ hoặc tất cả những thách thức liên quan đến thiết lập dòng nước ASCII này. Tất cả đều là môn đánh gôn, câu trả lời ngắn nhất cho mỗi thử thách là người chiến thắng. Câu trả lời được chấp nhận sẽ là người hoàn thành nhiều thử thách nhất, với tổng chiều dài mã là bộ ngắt kết nối.

Thử thách 1
Viết chương trình đưa ra một phần nước chảy vào các máng cho một lưới nhất định. Đầu ra của ví dụ trên chỉ đơn giản là 0.75.

Thử thách 2
Viết chương trình, được cung cấp một lưới, vẽ các điểm *ở những nơi nước chảy như tôi đã làm ở trên. Bạn không nên ghi đè lên bất cứ thứ gì ngoài các ký tự khoảng trắng và lưới không nên thay đổi kích thước. Vì vậy, đối với một cái gì đó như

 f
/A

không có gì cần phải làm vì mặc dù nước chảy ở hai bên của A, nhưng nó không thể bị hút về bên trái mà không cần tháo ra /và nó không thể được kéo sang bên phải mà không làm cho lưới 2 × 2 lớn hơn.

Thử thách 3 (Đã cập nhật)
Viết chương trình có hai số nguyên không âm, tổng T và số tiền giữ K (T> = K). Tạo và vẽ một lưới với chính xác một lưới fsao cho khi vòi đó đổ ra T đơn vị nước, chính xác K sẽ chảy vào các máng. Nếu không thể thực hiện điều này trong một lưới hữu hạn cho một cặp (T, K) cụ thể thì hãy xuất 'Không thể'.

Làm rõ (áp dụng cho tất cả các thử thách)

  • Đầu vào có thể thông qua stdin, hoặc một tệp hoặc thậm chí là một hàm gọi trên biểu diễn chuỗi của lưới. Chỉ cần làm cho nó rõ ràng làm thế nào để chạy đầu vào khác nhau.
  • Đầu ra phải đi đến thiết bị xuất chuẩn.
  • \AA/AAcũng máng như bạn mong muốn.
  • Lưới w by h sẽ luôn là một hình chữ nhật được định dạng tốt gồm các ký tự w * h không tính các dòng mới. Sẽ không có khoảng trống bị thiếu và không có sự xuất hiện của *.
  • Kích thước lưới có thể nhỏ bằng 1 × 1 và lớn tùy ý. (Lớn tùy ý trong lý do, int.maxValue hoặc tương tự là một giới hạn chấp nhận được. Tương tự với T và K.)
  • Một luồng trên một fdòng chảy qua nó.
  • Các vòi có thể ở bất cứ đâu, không chỉ ở hàng trên cùng.
  • A luôn chia lượng nước đổ vào chính xác một nửa.

Lưu ý: Những thứ như /A//hoàn toàn hợp lệ. Nước nào tự do chảy giữa các nhân vật (dù cho thách thức 2 không có đủ phòng để vẽ nó).

Vì vậy, trong thiết lập

ff

/A

Dòng fchảy bên trái đổ xuống, chạm vào /và dịch chuyển sang trái. fLuồng bên phải đổ xuống, chạm vào A, một nửa đi bên phải và một nửa đi bên trái giữa A/.

ví dụ

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

3
+1 Thử thách đẹp. Đối với thử thách 3, lưới ở trên cùng sẽ không phải là câu trả lời hợp lệ vì nó có 3 fs
edc65

@ edc65 À, bắt tốt!
Sở thích của Calvin


2
Đối với thử thách thứ hai, bạn cần chỉ định cách xử lý đầu vào như /Anếu nước rơi vào A. Đối với tất cả các thách thức, sẽ là tốt để làm rõ liệu \Alà một máng. Đối với thử thách thứ ba, có nên Agiả định 3 đơn vị rơi vào một phân tách 1.5 / 1.5(vì vậy đầu vào thực sự là một số hữu tỷ duy nhất) hoặc là 2 / 1, trong trường hợp nào bên nào nhận được 2?
Peter Taylor

1
@PeterTaylor Cảm ơn. Tôi đã làm rõ những điểm đó. Tôi đoán T và K có thể là số float nhưng tôi giữ chúng là số nguyên cho đơn giản. (Nhưng nếu T = 3 không trúng một Asau đó cả hai bên làm được 1,5 Nó tùy thuộc vào các coder để đảm bảo độ chính xác phao không phải là một vấn đề..)
Sở thích của Calvin

Câu trả lời:


3

Tất cả các thử thách C # 690byte (416byte + 274byte)

Thử thách 1 & 2 C # 579 446 416byte

Đây là một chương trình hoàn chỉnh nên thực hiện Thử thách 1 & 2. Nó đọc các dòng đầu vào từ stdin cho đến khi nhận được một dòng trống. Nó in ra kết quả cho Thử thách 2, và sau đó là kết quả cho Thử thách 1. Sử dụng lớp thập phân .NET để hy vọng tránh mọi lỗi làm tròn.

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);}}

Ít chơi gôn hơn:

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);
    }
}

Chạy thử (với không gian trống mà tôi hứa là có):

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

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

Thử thách 3 C # 274byte

Đây là một chương trình hoàn chỉnh mà nên hoàn Challenge 3. Tôi là một quản lý để tiết kiệm 6bytes bằng cách viết phân tích cú pháp số nguyên của riêng tôi để đọc các đầu vào chứ không phải Spliting một ReadLinevà sử dụng 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"));}}

Ít chơi gôn hơ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"));
    }
}

Chạy thử (một lần nữa thiếu không gian dấu mà tôi hứa là có):

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

3

Trước hết, tôi có một câu hỏi liên quan đến thử thách. Vì tôi không có đủ danh tiếng để nhận xét về câu hỏi, tôi sẽ viết nó ở đây:

  • Hành vi của /A(nước chảy trên A), //(nước chảy ở phía bên phải) và các biến thể của nguyên tắc này là gì? Nước có chảy đến "điểm tự do" đầu tiên ở bên hay không chảy "bên dưới" nước láng giềng?

Chỉ cần thử đơn giản, nó có thể được đơn giản hóa waaaaay (mà tôi sẽ làm sau bằng cách chỉnh sửa bài đăng này).

Chỉnh sửa: Phiên bản thứ hai, nhỏ hơn một chút. Tôi đã đi đến một cách tiếp cận khác: thay vì tìm kiếm từng ô để kiểm tra những gì đang đến từ đỉnh và hai bên, tôi bắt đầu từ vòi và "chảy" xuống dưới với đệ quy.

Javascript, 226 byte (Thử thách 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 byte (Thử thách 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 byte (Thử thách 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)};

Cách sử dụng

Cung cấp một đại diện hai chiều của bản đồ. Dưới đây là ví dụ được cung cấp trong câu hỏi:

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

Đầu ra

Thử thách 1: Đơn giản là sẽ tạo một hộp thoại (cảnh báo) với kết quả (0,75 cho ví dụ trên).

Thử thách 2: Nó sẽ trực tiếp sửa đổi bản đồ. Tôi có nên in nó? Nếu vậy, console.log có được chấp nhận không? làm đầu ra hợp lệ?

Thử thách 1 + 2: Cả hai kết hợp trên, rõ ràng ...


Nước cứ chảy giữa các nhân vật như thể nó đang ôm lấy những đường Agạch chéo hoặc. Tôi đã làm rõ điều đó trong câu hỏi.
Sở thích của Calvin

Câu hỏi nêu rõOutput must go to stdout.
user80551

Bạn đã chỉ định là định dạng đầu vào mà bạn có, đưa ra một chuỗi các chuỗi một ký tự trên mỗi hàng, nhưng hãy nhớ rằng bạn có thể lập chỉ mục str[0]thành các chuỗi. Đó sẽ là một chuỗi các chuỗi thay vì một mảng các ký tự.
tomsmeding

1
user80551 Cảm ơn, tôi không biết tại sao nó lại tuột khỏi tâm trí tôi. Tôi sẽ cập nhật mã của tôi càng sớm càng tốt. @tomsmeding Có, nó hoạt động cho câu trả lời của tôi về thử thách 1. Nhưng đối với thử thách 2 Tôi trực tiếp sửa đổi đầu vào và bạn không thể sửa đổi một ký tự trong chuỗi bằng str [i], do đó sử dụng một mảng các mảng.
refreshfr 23/07 '

2

Python 3, 186 byte (Thử thách 3)

Tôi lấy ý tưởng cho lưới từ câu trả lời của VisualMelon . Hàm nên in lưới hợp lệ thành thiết bị xuất chuẩn cho T và K lớn tùy ý, miễn là có thể (lưới kích thước hữu hạn) tất nhiên.

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ách sử dụng

Gọi chàm với tổng số tiền và số tiền để giữ làm đối số.

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

>>> c(6, 2)
Impossible
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.