pb , 359 byte
^w[B!0]{w[B=10]{t[T+1]b[0]}>}<w[T!0]{w[B!0]{<}>^b[T]vw[B!0]{t[B]b[0]^v[B]v<[X]w[B!0]{>}b[T]<[X]^[Y+2]w[B=0]{>}t[B]b[0]>b[T]v}^t[B-1]vw[B=0]{<}}>b[10]t[X]w[X!-2]{w[B!0]{v}<}w[X!T]{b[35]>}^[Y]^<[X]w[B!10]{t[B]b[0]w[T=35]{t[10]}v<[X]w[B!35]{w[B=0]{v<[X]<b[1]}>}b[T]^[Y]^<[X]w[B=0]{>}}<[X+2]w[B=0]{v}w[B!0]{b[0]>}w[Y!-1]{<[X]^w[B!0]{w[B=35]{b[0]}w[B=10]{b[35]}>}}
Trong pb, đầu vào là đúng một chiều. Nó không hiểu rằng bạn đang vẽ một hình dạng với đầu vào của bạn, nó chỉ nhìn thấy một dòng dài với một số byte có giá trị 10 được ném vào đó. Điều đầu tiên mà chương trình này thực hiện là sao chép tất cả trừ "dòng" đầu vào vào Y = 0, Y = 1, v.v., để tạo hình dạng của khuôn.
Một cái gì đó tôi đã nhận thấy rất nhiều trong mã golf, nhưng đặc biệt là khi chơi golf các ngôn ngữ bí truyền, là bạn thường không muốn có hai nhánh để giải quyết; bạn chỉ cần thiết lập rằng bạn làm điều tương tự trong cả hai trường hợp. Cách ngây thơ để giải quyết vấn đề này có lẽ sẽ kiểm tra độ dài của chuỗi so với số lần băm trong phần còn lại của đầu vào và làm một cái gì đó tùy thuộc vào kết quả, bởi vì nó phải hành xử khác nhau tùy thuộc vào những gì bị cắt. Nhưng đó là rất nhiều byte.
Thay vào đó, sau khi hoàn thành khuôn, một dòng phụ được thêm vào phía dưới. Nó chỉ đơn giản là n
băm liên tiếp, trong đón
là độ dài của chuỗi. Bây giờ chuỗi được đảm bảo để phù hợp! Sau khi chèn tất cả các ký tự của chuỗi, dòng bổ sung được thêm vào sẽ bị hủy vô điều kiện. Bất kỳ băm còn sót lại trong khuôn thích hợp cũng bị xóa, và đó là đầu ra cần thiết!
Tất nhiên, nó sẽ vi phạm thông số kỹ thuật chỉ đơn giản là phá hủy tất cả các băm. Rốt cuộc, có thể có một hàm băm trong chuỗi đầu vào! Để xử lý điều này, tôi tham khảo một phần khác của thông số:
Bạn được cung cấp một chuỗi ASCII có thể in duy nhất không chứa dòng mới
(Nhấn mạnh của tôi.) Vào thời điểm chúng tôi xử lý chuỗi, chúng tôi không thực sự quan tâm nếu có dòng mới trong đó, nhưng chúng tôi biết rằng không có bất kỳ. Vì vậy, tất cả các băm được thay thế bằng dòng mới trước khi đưa vào khuôn! Sau khi tất cả các băm bị hủy, tất cả các dòng mới được thay thế bằng băm một lần nữa. Điều này không biến toàn bộ đầu ra thành một dòng được phân tách bằng hàm băm bởi vì bản chất của đầu ra 2D của pb có nghĩa là nó không bao giờ thực sự đặt một dòng mới ở cuối mỗi dòng, nó chỉ chuyển sang dòng tiếp theo.
Ung dung:
# Start by copying down the mold
^
# (B means "the character under the cursor")
w[B!0]{ # While B isn't a null byte:
w[B=10]{ # While B IS a newline:
t[T+1] # Increase T by 1
# (`T` is the only variable that can be modified directly)
b[0] # Overwrite with 0 to break out of inner loop
}
> # Move to the right
# (dodge the 0 we wrote and progress towards the end of input)
}
# Brush is now at the end of the input, T contains number of lines
< # Make sure the brush is actually /on/ the input
w[T!0]{ # While T isn't 0:
w[B!0]{<}> # Go to the first character of the last line
^b[T] # Place a flag above current character
# Also a convenient way to get the value of T back later
vw[B!0]{ # While the character under the flag isn't 0:
t[B]b[0] # Put it in T, overwrite with 0
^v[B]v # Go down by the amount written in the space above
<[X] # Go left by the amount right the brush is (i.e. go to X=0)
w[B!0]{>} # Find first empty space
b[T] # Write the value of T
<[X] # Go left by the amount right the brush is
^[Y+2] # Go up by the amount down the brush is plus 2 (above input)
w[B=0]{>} # Find flag
t[B]b[0] # Pick it up, overwrite with 0
>b[T] # Place it to the right
v}
^t[B-1]v # Collect flag - 1
w[B=0]{<} # Go to end of previous line
}
# Mold is placed, all that's left is placing the string
>b[10] # Put a newline at the end, guaranteed to not be in the string
t[X] # Save current X value in T
# Add more hashes, guaranteed to fit the input and findable later
w[X!-2]{ # While X!=-2:
w[B!0]{v} # Move down until hitting a null byte
< # Move left
}
w[X!T]{ # While not at the X value we saved earlier:
b[35]> # Travel right, leaving hashes
}
^[Y]^<[X] # Go to (0, -1)
w[B!10]{ # Until hitting the newline at the end:
t[B]b[0] # Pick up character, overwrite with 0
w[T=35]{ # If it's a hash...
t[10] # Make it a newline so we remember, deal with it later
}
v<[X] # Go to (0, 0)
w[B!35]{ # While B is not a hash:
w[B=0]{ # While B IS null:
v # Go down
<[X]< # Go to X=-1
b[1] # Print a 1 to break loop (it won't be rendered anyway)
}
> # Go right, either ignore a non hash or go to X=0
}
b[T] # Overwrite hash with picked up character
^[Y]^<[X] # Go to (0, -1)
w[B=0]{>} # Go to first character of it to restart loop
}
<[X+2] # Go to (-2, -1)
w[B=0]{v} # Go down until finding the row of added hashes
w[B!0]{b[0]>} # Wipe it out unconditionally
w[Y!-1]{ # For every remaining line on the screen:
<[X]^ # Go to the beginning
w[B!0]{ # For each character in it:
w[B=35]{ # If it's a hash:
b[0] # Destroy it
}
w[B=10]{ # If it's a newline:
b[35] # Write a hash (after the check to destroy hashes!)
}
>}
}