โพลีโอมิโนเส้นรอบวงสูงสุด


14

นี่คือรหัสกอล์ฟ ผู้ชนะคือรหัสที่ถูกต้องและมีจำนวนไบต์น้อยที่สุด


ท้าทาย

รับอินพุตMและN , ความกว้างและความสูงของตารางสี่เหลี่ยมของสี่เหลี่ยม, ส่งออกรูปหลายเหลี่ยมที่ตรงตามต่อไปนี้:

  • ขอบรูปหลายเหลี่ยมสร้างขึ้นจากขอบสี่เหลี่ยมเท่านั้น:ไม่มีขอบทแยงมุม - ทั้งหมดเป็นแนวตั้งหรือแนวนอน
  • รูปหลายเหลี่ยมไม่มีรู:สี่เหลี่ยมด้านนอกของรูปหลายเหลี่ยมนั้นอาจถึงได้โดยขั้นตอนมุมฉากบนสี่เหลี่ยมนอกรูปหลายเหลี่ยมเริ่มจากสี่เหลี่ยมนอกรูปหลายเหลี่ยมบนขอบเขตด้านนอกของรูปสี่เหลี่ยมผืนผ้า
  • รูปหลายเหลี่ยมนั้นไม่มีจุดตัดเอง:จากการที่ขอบจตุรัสพบกันที่จุดยอดไม่เกิน 2 อาจเป็นส่วนหนึ่งของเส้นรอบวงรูปหลายเหลี่ยม
  • รูปหลายเหลี่ยมถูกเชื่อมต่อ:สี่เหลี่ยมใด ๆ ในรูปหลายเหลี่ยมจะต้องสามารถเข้าถึงได้จากตารางอื่น ๆ ในรูปหลายเหลี่ยมผ่านขั้นตอนมุมฉากที่อยู่ภายในรูปหลายเหลี่ยม
  • รูปหลายเหลี่ยมมีขอบเขตสูงสุดที่เป็นไปได้:ตามสูตรที่แสดงด้านล่าง

รหัสของคุณจะต้องใช้กับMและN ได้ตั้งแต่ 1 ถึง 255


สูตรสำหรับปริมณฑลสูงสุด

ความท้าทายที่นี่คือการค้นหาความสามารถในการเล่นกอล์ฟของรูปหลายเหลี่ยมที่มีขอบเขตสูงสุด ขอบเขตสูงสุดนั้นถูกกำหนดโดยสูตรเสมอ:

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


เอาท์พุต

แสดงรูปร่างเป็นสตริงของอักขระที่คั่นด้วยบรรทัดใหม่ ( แถวNของอักขระM ทั้งหมด ) ที่นี่ฉันกำลังใช้พื้นที่สำหรับสี่เหลี่ยมนอกรูปหลายเหลี่ยมและ '#' สำหรับกำลังสองภายในรูปหลายเหลี่ยม แต่คุณสามารถใช้อักขระสองตัวที่แตกต่างกันได้โดยให้ความหมายสอดคล้องกับอินพุตทั้งหมด

คุณสามารถรวมบรรทัดใหม่ชั้นนำได้หนึ่งรายการและขึ้นบรรทัดใหม่ต่อท้ายหนึ่งรายการ

หากคุณต้องการคุณสามารถส่งออกแถวM ที่มีอักขระทั้งหมดNตัวและคุณอาจเลือกMเอาต์พุต by Nสำหรับอินพุตบางตัวและเอาต์พุตNโดยMสำหรับผู้อื่น


ตัวอย่าง

ไม่ถูกต้องเนื่องจากมีรู:

###
# #
###

ไม่ถูกต้องเนื่องจากจุดตัด (สัมผัสแนวทแยงมุม - จุดยอดที่มีขอบสี่เหลี่ยมจตุรัส 4 อันบนขอบเขต) และโดยบังเอิญเป็นรู:

##
# #
###

ไม่ถูกต้องเนื่องจากถูกตัดการเชื่อมต่อ:

#
# #
  #

รูปหลายเหลี่ยมที่ถูกต้องของขอบเขตสูงสุด:

# #
# #
###

เครดิต

ตอนแรกฉันประเมินค่าต่ำสุดว่าสามารถคำนวณค่าขอบเขตสูงสุดได้เร็วเพียงใดและจะถามค่านั้นเป็นผลลัพธ์ ขอขอบคุณผู้คนที่เป็นประโยชน์อย่างยิ่งในการแชทเพื่ออธิบายวิธีการใช้ขอบเขตสูงสุดสำหรับ N และ M โดยพลการและช่วยให้สิ่งนี้กลายเป็นความท้าทายที่จะคงอยู่นานกว่าหนึ่งคำตอบ ...

ขอขอบคุณเป็นพิเศษกับ:

SPARR , Zgarb , feersum , jimmy23013


ฉันตั้งชื่อคำถามนี้โดยใช้ polyominos หรือรูปหลายเหลี่ยม (เนื่องจากทั้งคู่มีผลบังคับใช้) ใครบ้างที่มีความชอบ? คุณสามารถระบุด้วยความคิดเห็นการลงคะแนนในต่อไปนี้:
trichoplax


1
รูปหลายเหลี่ยมที่เชื่อมต่อกันในขอบเขตสูงสุด
trichoplax

N แถวของอักขระ M ทั้งหมด: เราสามารถแลกเปลี่ยนค่าอินพุตสองค่าได้หรือไม่หากเราคิดว่าสะดวกสำหรับอินพุตบางตัว?
เลเวลริเวอร์

3
@steveverrill ฉันได้แก้ไขส่วนผลลัพธ์ สิ่งนี้เหมาะสมกับคำขอของคุณหรือไม่?
trichoplax

คำตอบ:


4

CJam, 47 ไบต์

l~_2%{\}|_'#:H*@({N+1$(2md\HS+*H+\SH+R=*++}fR\;

ลองออนไลน์

คำอธิบาย:

l~      Get and convert input.
_2%     Calculate second value modulo 2.
{\}|    If value is even, swap the two inputs. This puts odd on top if one is odd.
_'#:H*  Create top row of all # signs. Also save away # character as shortcut for later.
@(      Pull number of rows to top, and decrement because first is done.
{       Start loop over rows.
N+      Add newline.
1$      Copy row length to top of stack.
(2md    Decrement, and calculate mod/div with 2.
\       Swap mod and div, will use div first.
HS+     "# "
*       Repeat it based on div 2 of row length.
H+      Add one more #.
\       Swap mod of earlier division to top.
SH+     " #"
R=      Pick space or # depending on even/odd row number.
*       Repeat 0 or 1 times depending on mod 2 of row length.
+       Add the possible extra character to line.
+       Add line to result.
}fR     End of for loop over lines.
\;      Remove row length from stack, leaving only result string.

มีสองกรณีหลักสำหรับผลลัพธ์ หากมีอย่างน้อยหนึ่งขนาดที่แปลกรูปแบบจะเป็น "เรค" แบบธรรมดา ตัวอย่างเช่นสำหรับอินพุต7 6:

#######
# # # #
# # # #
# # # #
# # # #
# # # #

หากทั้งสองขนาดเท่ากันจะมีคอลัมน์พิเศษที่ทุกตารางที่สองคือ "เปิด" ตัวอย่างเช่นสำหรับอินพุต8 6:

########
# # # # 
# # # ##
# # # # 
# # # ##
# # # # 

ตอนนี้เพื่อแสดงให้เห็นว่ารูปแบบเหล่านี้มีค่าสูงสุดตามทฤษฎีของขอบเขตที่ระบุไว้ในคำอธิบายปัญหาเราต้องยืนยันว่ารูปแบบแรกมีขอบเขต (M + 1) * (N + 1)และส่วนที่สองมีค่าเท่ากันลบ 1

สำหรับรูปแบบแรกเรามีขอบเขตโดยMมีมิติที่แปลก:

  1. M สำหรับขอบด้านบน
  2. 2 ที่ด้านข้างของแถวบน
  3. (M - 1) / 2 สำหรับช่องว่างระหว่างฟัน
  4. (M + 1) / 2ฟันด้วยเส้นรอบวง2 * (N - 1) + 1แต่ละอัน

สิ่งนี้จะรวมถึง:

M + 2 + (M - 1) / 2 + (M + 1) / 2 * (2 * (N - 1) + 1) =
M + 2 + (M - 1) / 2 + (M + 1) * (N - 1) + (M + 1) / 2 =
2 * M + 2 + (M + 1) * (N - 1) =
(M + 1) * 2 + (M + 1) * (N - 1) =
(M + 1) * (N + 1)

สำหรับกรณีที่สองที่ทั้งคู่MและNสม่ำเสมอปริมณฑลจะเพิ่มขึ้นจาก:

  1. M สำหรับขอบด้านบน
  2. 2 ที่ด้านข้างของแถวบน
  3. M / 2 สำหรับ open # ในแถวบนสุด
  4. M / 2ฟันกับปริมณฑล2 * (N - 1) + 1แต่ละสำหรับฟันธรรมดา
  5. ฟันขวาสุดมี2 * (N / 2 - 1)ชิ้นส่วนเสริมพิเศษสำหรับ jaggies

การเพิ่มสิ่งนี้เข้าด้วยกัน:

M + 2 + M / 2 + (M / 2) * (2 * (N - 1) + 1) + 2 * (N / 2 - 1) =
M + 2 + (M / 2) * (2 * (N - 1) + 2) + N - 2 =
M + M * N + N =
(M + 1) * (N + 1) - 1

ฉันคิดว่าฉันสามารถบันทึกสองสามไบต์ได้โดยวางส่วนที่ขรุขระไว้ทางซ้าย ควรมีการสับซ้อนน้อยกว่า แต่ถึงเวลานอนแล้ว ...
Reto Koradi

5

Ruby, Rev 1, 66

->(m,n){n.times{|i|puts ("#"*m**(1-i%2)).rjust(m,i>n-2?"# ":" ")}}

ใช้การเพิ่มmกำลัง 0 o 1 เพื่อตัดสินใจว่า 1 หรือm #จะพิมพ์ไม่

ใช้>เพื่อทดสอบแถวสุดท้ายแทน==ในการทดสอบสำหรับแถวสุดท้ายแทน

ไม่สามารถกำจัดพื้นที่หลังจากใส่หรือวงเล็บใด ๆ !

Ruby, Rev 0, 69

->(m,n){n.times{|i|puts ("#"*(i%2==0?m:1)).rjust(m,i==n-1?"# ":" ")}}

นี่คือฟังก์ชั่นแลมบ์ดานิรนาม ใช้มันแบบนี้:

f=->(m,n){n.times{|i|puts ("#"*(i%2==0?m:1)).rjust(m,i==n-1?"# ":" ")}}

M=gets.to_i
N=gets.to_i
f.call(M,N)

ในท้ายที่สุดหลังจากถามว่า M และ N สามารถสับเปลี่ยนกันได้หรือไม่ฉันไม่ต้องการมัน


เอาต์พุตทั่วไปสำหรับ N คี่ หากเราลบ#ตัวเองทางด้านขวามือเราจะมี (N + 1) (M + 1) การรวมพวกมันเข้าด้วยกันจะเป็นการลบเส้นรอบวงแนวนอน 2 สี่เหลี่ยมและเพิ่มเส้นแนวตั้งแนวนอน 2 สี่เหลี่ยมดังนั้นจึงไม่มีการเปลี่ยนแปลง

ที่นี่เราพึ่งพาการแสดงออก"#"*(i%2==0?m:1)เพื่อให้สลับแถวของ#สัญลักษณ์M และหนึ่ง#สัญลักษณ์และจัดชิดขวาให้กับอักขระ M

5                        6
5                        5
#####                    ######
    #                         #
#####                    ######
    #                         #
#####                    ######

เอาต์พุตทั่วไปสำหรับ N สม่ำเสมอ 5 6เห็นได้ชัดว่ามีขอบเขตเดียวกับ6 5หรือการเพิ่มขึ้นของ M + 1 = 6 เมื่อเทียบกับการ5 5เพิ่มขึ้นของแนวตั้งในแนวตั้งเนื่องจากความหนาแน่นของแถวด้านล่าง 6 6มีเช่นเดียวกับ6 5บวกการเพิ่มขึ้นของ (M + 1) -1 = 6 ในขอบเขตแนวตั้ง ดังนั้นพวกเขาเป็นไปตามสูตร

5                        6
6                        6
#####                    ######
    #                         #
#####                    ######
    #                         #
#####                    ######
# # #                    # # ##

เป็นประโยชน์อย่างมากที่รูบี้rjustให้คุณระบุช่องว่างภายในสำหรับเซลล์ว่าง ปกติแล้วการเติมจะถูกตั้งค่าเป็น" "แต่สำหรับแถวสุดท้ายเราสลับไปที่"# "(โปรดทราบว่าการเติมจะจำเป็นเฉพาะในแถวสุดท้ายถ้า N เป็นเลขคู่โดยที่ N เป็นเลขคี่แถวสุดท้ายจะสมบูรณ์และจะไม่มีการจัดชิดขอบดังนั้นคุณ จะไม่เห็น crenelations)

ตรวจสอบที่นี่


@ Vioz- ขอบคุณสำหรับ ideone! ฉันทดสอบโปรแกรมลงไปที่ค่าต่ำสุดของ N และ M เพื่อดูว่ามีกรณีขอบหรือไม่ เห็นได้ชัดว่าทั้ง crenellation และ crenelation นั้นถูกต้องดังนั้นฉันจะทิ้งมันไว้ จะกลับมาใหม่ในภายหลังเพื่อดูว่าฉันสามารถลบวงเล็บและช่องว่างได้ไหม
เลเวลริเวอร์

ไม่มีปัญหาสำหรับลิงค์? ฉันคิดว่ามันจะมีประโยชน์สำหรับคนอื่น ๆ ตั้งแต่ฉันใช้มันเพื่อทดสอบ: P เกี่ยวกับการแก้ไขการสะกดฉันเปลี่ยนมันเป็นผลลัพธ์แรกที่ฉันพบเพราะฉันไม่เคยเห็นคำที่ใช้จริง ผมไม่ทราบว่ามากเกี่ยวกับทับทิม (อะไร Infact) แต่คุณสามารถเปลี่ยนi%2==0ไปi%2<1เพื่อประหยัดไบต์ (ผมเคยทำการเปลี่ยนแปลงนี้เพื่อเชื่อมโยง ideone) ที่
Kade

คุณต้องการ#ช่องว่างภายในสำหรับแถวสุดท้ายหรือไม่? ตัวอย่างเช่นในรูปสุดท้ายขอบเขตไม่เหมือนกันหากไม่มีที่#มุมล่างขวาใช่ไหม
Reto Koradi

@RetoKoradi จริง ๆ แล้วมันจะเป็นเส้นรอบวงเดียวกัน - ดูเหมือนว่ารหัสรวมพิเศษ#เพียงเพราะมันมีอยู่แล้ววิธีที่ทุกบรรทัดจะจบลงดังนั้นจึงมีไบต์น้อยกว่าการวางช่องว่างที่นั่น (ฉันไม่รู้ทับทิมว่า ... )
trichoplax

1
@trichoplax สัญชาตญาณของคุณถูกต้อง การขยาย"# "ไม่ได้เป็น" #"เพราะหลังจะให้ 2 ที่อยู่ติดกัน#สำหรับ M คี่ซึ่งไม่ต้องการแน่นอน 2 ที่อยู่ติดกัน#สำหรับ M แม้จะไม่เป็นอันตรายดังนั้นฉันจึงไปกับที่ ฉันยังไม่ได้ลองljustมันอาจเป็นไปได้ที่จะทำอย่างนั้นมากขึ้น แต่ก็ไม่ชัดเจนว่าฉันจะพิมพ์อักขระ M ต่อแถวอย่างแน่นอน
เลเวลริเวอร์เซนต์

5

C, 109 97 ไบต์และการพิสูจน์ความถูกต้อง

ฉันกำลังเขียนคำตอบของฉัน แต่ @steveverrill เอาชนะฉันได้ ฉันคิดว่าฉันจะแบ่งปันทุกอย่างเหมือนกันเนื่องจากฉันได้รวมหลักฐานความถูกต้องสำหรับกลยุทธ์ที่ใช้

รหัสที่ลดลง:

m,n,x;main(){for(scanf("%i%i",&m,&n); n;)putchar(x<m?"# "[x%2*(++x^m||~n&1)&&n^1]:(x=0,n--,10));}

ก่อนลด:

m,n,x;

main(){
    for(scanf("%i%i",&m,&n); n;) 

        /* If x == m, prints out a newline, and iterates outer 
         * loop (x=0,n--) using comma operator.
         * Otherwise, paints a '#' on :
         *     Every even column (when x%2 is 0)
         *     On odd columns of the last row (++x^m||~n&1 is 0)
         *     On the first row (when n^1 is 0)
         * And a ' ' on anything else (when predicate is 1) */
        putchar(x<m?"# "[x%2*(++x^m||~n&1)&&n^1]:(x=0,n--,10));
}

กลยุทธ์และหลักฐาน:

สมมติว่าความถูกต้องของสมการสูงสุดของปริภูมิ(M + 1) (N + 1) - ((M + 1) (N + 1)) mod 2ต่อไปนี้จะอธิบายถึงกลยุทธ์ที่ดีที่สุดที่ใช้และพิสูจน์ความถูกต้องโดยการเหนี่ยวนำ:

สำหรับคี่ M เราวาดรูปร่างเหมือนมือด้วย M / 2 + 1 นิ้วตัวอย่างเช่น

3x2
# # 
###

5x3
# # #
# # #
#####

ตอนนี้เราพิสูจน์แล้วว่ากลยุทธ์นี้ดีที่สุดสำหรับคี่ M ทั้งหมดโดยการเหนี่ยวนำ:

Case Base: M = N = 1
มีการเติมเซลล์เดียว การแก้ปัญหานั้นถูกต้องตั้งแต่ (1 + 1) * (1 + 1) = 2 * 2 = 4 และสี่เหลี่ยมจัตุรัสมี 4 ด้าน

การเหนี่ยวนำในความกว้าง:
สมมติว่ากลยุทธ์รูปร่างมือใช้งานได้สำหรับ(N, M-2)โดยที่ M เป็นเลขคี่นั่นคือ perimiter นั้นเหมาะสมที่สุดและ(N + 1) (M - 2 + 1) + ((M -1) (N + 1)) mod 2 ตอนนี้เราแสดงให้เห็นว่ามันใช้งานได้สำหรับ(N, M)M)

กระบวนการของการเพิ่มนิ้วเอาหนึ่งขอบจากรูปหลายเหลี่ยมและเพิ่ม3 + 2N ตัวอย่างเช่น:

 5x3 -> 7x3
 # # # $
 # # # $
 #####$$

เมื่อรวมกับสมมติฐานของเราว่าขอบเขตก่อนหน้านี้เหมาะสมที่สุดขอบเขตใหม่คือ:

(N + 1)*(M - 2 + 1) - ((M+1)*(N+1)) mod 2 - 1 + 3 + 2*N
(N + 1)*(M + 1) - ((M-1)*(N+1)) mod 2 - 2(N + 1) - 1 + 3 + 2*N
(N + 1)*(M + 1) - ((M-1)*(N+1)) mod 2

เนื่องจากเรากำลังติดต่อกับ modulo 2 เลขคณิต

((M-1)*(N+1)) mod 2 = ((M+1)*(N+1)) mod 2

ดังนั้นการพิสูจน์ว่าการเพิ่มความกว้างโดยการเพิ่มนิ้วนำไปสู่ขอบเขตที่เหมาะสม

การเหนี่ยวนำต่อความสูง:
สมมติว่ากลยุทธ์แบบมือถือใช้งานได้สำหรับ(N-1, M)โดยที่Mเป็นเลขคี่นั่นคือขอบเขตของมันจะเหมาะสมที่สุดและเป็นN (M + 1) + ((M + 1) N) mod 2 . ตอนนี้เราแสดงให้เห็นว่ามันใช้งานได้สำหรับ(N, M)M)

การเพิ่มความสูงของมือนั้นเพียงแค่ยืดนิ้วมือซึ่งตั้งอยู่ที่ดัชนี x ตัวแรกและตัวอื่น ๆ สำหรับความสูงที่เพิ่มขึ้นแต่ละนิ้วแต่ละนิ้วจะเพิ่มสองเส้นรอบวงและมี(M + 1) / 2นิ้วดังนั้นการเพิ่มขึ้นของNจะนำไปสู่การเพิ่มขึ้นของ2 (M + 1) / 2 = M + 1ใน ปริมณฑล.

เมื่อรวมกับสมมติฐานนี้เรามีขอบเขตใหม่คือ:

N*(M + 1) + ((M+1)*N) mod 2 + M + 1
(N + 1)*(M + 1) + ((M+1)*N) mod 2

การคำนวณแบบแยกส่วนช่วยให้เราสามารถทำให้คำสุดท้ายง่ายขึ้นดังนั้นเราจึงได้รับ:

(N + 1)*(M + 1) + ((M+1)*(N+1)) mod 2

การพิสูจน์ว่าโซลูชันนั้นเหมาะสมที่สุดสำหรับ N> 0 และคี่ M> 0

สำหรับแม้แต่ M เราเติมบอร์ดเดียวกับที่เราทำกับคี่ M แต่เราเพิ่ม crenelations ในเซ็กเมนต์สุดท้ายเช่น:

4x3
# ##
# # 
####

6x4
# # #
# # ##
# # #
######

ตอนนี้เราพิสูจน์แล้วว่ากลยุทธ์นี้เหมาะสมที่สุด

การเหนี่ยวนำสำหรับแม้แต่ M:
สมมติว่าคำตอบนั้นถูกต้องสำหรับ (N, M-1) โดยมี M-1 คี่ (ดังที่พิสูจน์แล้วในกรณีสุดท้าย) ซึ่งมีขอบเขตที่เหมาะสมของ(N + 1) M - ( M (N + 1)) mod 22 ตอนนี้เราแสดงให้เห็นว่ามันใช้งานได้สำหรับ (N, M)

เช่นเดียวกับการเพิ่มนิ้วมือการรับรู้ภาพแต่ละภาพจะเพิ่มสองมุมของรูปหลายเหลี่ยม จำนวนรวมของ crenelations คือ(N + N mod 2) / 2 , รวมเป็นN + N mod 2เพิ่มปริมณฑล

เมื่อรวมกับสมมติฐานนี้เรามีขอบเขตใหม่คือ:

(N + 1)*M - (M*(N+1)) mod 2 + N + N mod 2
(N + 1)*(M + 1) - (M*(N+1)) mod 2 + N mod 2 - 1
(N + 1)*(M + 1) - (M*(N+1)) mod 2 - (N + 1) mod 2

เรามีสิ่งนั้น

(M*(N+1)) mod 2 - (N + 1) mod 2 = ((M+1)*(N+1)) mod 2

เนื่องจากถ้า N เป็นเลขคี่ค่านี้จะลดลงเป็น 0 = 0 และถ้า N เป็นเลขคู่จะลดลงเป็น

- A mod 2 - 1 = -(A + 1) mod 2

ดังนั้นกลยุทธ์ที่เป็นที่เหมาะสมสำหรับทุกM, N> 0


2
นั่นเป็นคณิตศาสตร์จำนวนมาก! คุณไม่สามารถคำนวณขอบเขตของรูปร่างที่คุณสร้างขึ้นและแสดงว่ามันตรงกับค่าสูงสุดที่ให้มาได้หรือไม่ คุณรู้ว่าคุณมี "นิ้ว" กี่นิ้วแต่ละนิ้วมีระยะเวลานานเท่าใดดังนั้นการคำนวณเส้นรอบวงควรจะง่ายพอสมควร
Reto Koradi

จริง ในบางประเด็นฉันรู้สึกว่าเส้นทางการเหนี่ยวนำนั้นง่ายกว่าเดิมเนื่องจากมันเป็นสารเติมแต่ง แต่ใช่มันนำไปสู่คำอธิบายที่ยาวขึ้น
André Harder

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