현장의 요소를 맞추십시오


11

1000보다 작은 양의 정수가 주어지면 해당 영역으로 가능한 모든 사각형을 표시하십시오.

직무

입력이 20이라고 가정 해 봅시다. 사각형을 20 × 1, 10 × 2 또는 5 × 4로 만들 수 있습니다.

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

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

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

가능한 각 사각형은 정확히 한 번 나타납니다.

사각형은 임의의 순서, 방향 또는 위치로 나타날 수 있지만 모서리에서도 두 사각형이 겹치거나 닿을 수 없습니다. 다음도 유효합니다.

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

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

채점

출력의 경계 상자 영역 (BBA)은 모든 사각형을 포함하는 최소 사각형의 영역입니다. 첫 번째 예제 출력에서 ​​크기는 20x9이므로 BBA는 180입니다. 두 번째 예제 출력에서 ​​크기는 20x7이므로 BBA는 140입니다.

입력이 60, 111, 230, 400 및 480 일 때 출력의 BBA를 찾아 합산하십시오. 이 합계에 코드 크기 (바이트)를 곱하십시오. 결과는 당신의 점수입니다; 최저 점수가 이깁니다.

규칙

  • 프로그램 (또는 함수)은 1000 미만의 양의 정수에 대해 유효한 출력을 생성해야합니다.
  • 출력에는 별표 ( *), 공백 ( ) 및 줄 바꿈 만 포함되어야합니다 .
  • 사각형 사이에는 어느 정도의 공간이있을 수 있지만 이는 BBA에 포함됩니다.
  • 공백이나 공백이있는 경우 선행 또는 후행 줄 또는 열은 BBA에 포함되지 않습니다.

특별한 경우를 하드 코딩 할 수 있습니까?
Calvin 's Hobbies

@ Calvin'sHobbies 네,하지만 많은 도움이 될 것 같습니다.
Ypnypn

3
@ Calvin'sHobbies 폭스 바겐 솔루션.
Level River St

답변:


3

루비, 228 바이트 * 21895 = 4992060

->n{a=(0..n*2).map{$b=' '*n}
g=0
m=n*2
(n**0.5).to_i.downto(1){|i|n%i<1&&(m=[m,n+h=n/i].min
g+=h+1
g<m+2?(a[g-h-1,1]=(1..h).map{?**i+$b}):(x=(m-h..m).map{|j|r=a[j].rindex(?*);r ?r:0}.max 
(m-h+1..m).each{|j|a[j][x+2]=?**i}))}
a}

ungolfed 코드에서 몇 가지 변경. 가장 큰 것은 가장 m사각형의 높이에서 가장 사각형의 높이에 으로 변하는 의미의 변화입니다 n.

사소한 *40것으로 변경되어 *n오른쪽에 불필요한 공백이 많음을 의미합니다 n. 과 -2로 변경 0되는 하단에 그려진 수단 사각형은 항상 (만 인수 분해입니다 숫자 가난한 포장이 결과 처음 두 열을 그리워 (n/2)*2)

설명

나는 마침내 이것으로 돌아갈 시간을 찾았다.

주어진 n가장 작은 필드에는 가장 긴 사각형 1*n과 가장 사각형에 충분한 공간이 있어야합니다 x*y. 두 직사각형의 장변이 같은 방향으로 배열되어 있으면 최상의 레이아웃을 얻을 수 있습니다.

사각형 사이의 공백에 대한 요구 사항을 무시하면 총 면적이 (n+y)*x = (n+n/x)*x또는 n*(x+1)입니다. 어느 쪽이든, 이것은로 평가됩니다 n*x + n. 공백을 포함 x하여 사각형을 끝까지 n배치하거나 사각형을 나란히 배치하는 경우 추가를 포함시켜야합니다 . 따라서 전자가 바람직하다.

(n+y+1)*x필드 영역에 대한 다음 하한 을 제공합니다 .

n     area
60    71*6=426
111  149*3=447
230  254*10=2540
400  421*20=8240
480  505*20=10100

이것은 다음 알고리즘을 제안합니다.

Find the value (n+y+1) which shall be the field height
Iterate from the squarest rectangle to the longest one
  While there is space in the field height, draw each rectangle, one below the other, lined up on the left border.
  When there is no more space in the field height, draw the remaining rectangles, one beside the other, along the bottom border, taking care not to overlap any of the rectangles above.
  (Expand the field rightwards in the rare cases where this is necessary.)

60을 제외하고 위에서 언급 한 하한 내에서 필요한 테스트 사례에 대한 모든 사각형을 얻는 것이 실제로 가능합니다. 60은 다음 71 * 8 = 568 출력을 제공합니다. 가장 얇은 두 사각형을 한 정사각형으로 이동 한 다음 위쪽으로 이동하면 약간 60 * 9 = 540으로 약간 향상 될 수 있지만, 저장 비용은 최소화되므로 추가 코드를 사용할 가치가 없습니다.

10
12
15
20
30
60
******
******
******
******
******
******
******
******
******
******

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

총 면적은 21895입니다.

Ungolfed 코드

f=->n{
  a=(0..n*2).map{' '*40}                                      #Fill an array with strings of 40 spaces
  g=0                                                         #Total height of all rectangles
  m=n                                                         #Height of squarest rectangle (first guess is n) 
  (n**0.5).to_i.downto(1){|i|n%i<1&&(puts n/i                 #iterate through widths. Valid ones have n%i=0. Puts outputs heights for debugging.
    m=[m,h=n/i].min                                           #Calculate height of rectangle. On first calculation, m will be set to height of squarest rectangle.
    g+=h+1                                                    #Increment g
    g<n+m+2?                                                  #if the rectangle will fit beneath the last one, against the left margin
      (a[g-h-1,1]=(1..h).map{'*'*i+' '*40})                      #fill the region of the array with stars
    :                                                         #else  
      (x=(n+m-h..n+m).map{|j|r=a[j].rindex('* ');r ?r:-2}.max    #find the first clear column
      (n+m-h+1..n+m).each{|j|a[j][x+2]='*'*i}                    #and plot the rectangle along the bottom margin
    )
  )}
a}                                                            #return the array

puts f[gets.to_i]


1

루비, 56 바이트

90385 * 56 = 5061560 출력을 Martin과 동일하다고 가정합니다 (그렇다고 생각합니다).

->n{1.upto(n){|i|i*i<=n&&n%i==0&&puts([?**(n/i)]*i,'')}}

유용한 테스트 프로그램의 또 다른 유용한 기능이 있습니다.

f=->n{1.upto(n){|i|i*i<=n&&n%i==0&&print(n/i,"*",i,"\n")};puts}

f[60];f[111];f[230];f[400];f[480]

다음은 참조 용으로 다음과 같은 출력을 제공합니다.

60*1
30*2
20*3
15*4
12*5
10*6

111*1
37*3

230*1
115*2
46*5
23*10

400*1
200*2
100*4
80*5
50*8
40*10
25*16
20*20

480*1
240*2
160*3
120*4
96*5
80*6
60*8
48*10
40*12
32*15
30*16
24*20
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.