To jest kod golfowy. Zwycięzcą jest prawidłowy kod o najmniejszej liczbie bajtów.
Wyzwanie
Przy danych wejściowych M i N szerokość i wysokość prostokątnej siatki kwadratów daje wielokąt spełniający następujące kryteria:
- Krawędzie wielokątów składają się tylko z kwadratowych krawędzi: nie ma krawędzi ukośnych - wszystkie są pionowe lub poziome.
- Wielokąt nie ma otworów: do każdego kwadratu poza wielokątem można dotrzeć prostopadłymi krokami na kwadratach poza wielokątem, zaczynając od kwadratu poza wielokątem na zewnętrznej granicy prostokąta.
- Wielokąt nie ma własnego przecięcia: kwadratowych krawędzi spotykających się w wierzchołku nie więcej niż 2 mogą stanowić część obwodu wielokąta.
- Wielokąt jest połączony: każdy kwadrat w wielokącie musi być osiągalny z dowolnego innego kwadratu w wielokącie poprzez ortogonalne kroki, które pozostają w obrębie wielokąta.
- Wielokąt ma maksymalny możliwy obwód: zgodnie ze wzorem pokazanym poniżej.
Twój kod musi działać dla M i N od 1 do 255.
Wzór na maksymalny obwód
Wyzwanie polega na znalezieniu grywalnych wielokątów o maksymalnym obwodzie. Sam maksymalny obwód jest zawsze określony przez wzór:
Jest tak, ponieważ dla maksymalnego obwodu każdy kwadratowy wierzchołek musi znajdować się na obwodzie. W przypadku nieparzystej liczby wierzchołków nie jest to możliwe, a najlepsze, co można osiągnąć, to jeden wierzchołek mniej (ponieważ obwód jest zawsze równy).
Wynik
Wyjście kształtu jako ciąg znaków rozdzielonych znakiem nowej linii ( N wierszy dokładnie M znaków). Tutaj używam spacji dla kwadratów poza wielokątem i „#” dla kwadratów wewnątrz wielokąta, ale możesz użyć dowolnych dwóch wizualnie różnych znaków, pod warunkiem, że ich znaczenie jest spójne dla wszystkich danych wejściowych.
Możesz dołączyć do jednego wiodącego nowego wiersza i do jednego końcowego nowego wiersza.
Jeśli chcesz, możesz zamiast tego wypisać M wierszy dokładnie N znaków i możesz wybrać wyjście M na N dla niektórych danych wejściowych i N na M danych wyjściowych dla innych.
Przykłady
Nieprawidłowy z powodu dziury:
###
# #
###
Nieprawidłowy ze względu na przecięcie (dotykanie po przekątnej - wierzchołek o 4 kwadratowych krawędziach na obwodzie) i, nawiasem mówiąc, otwór:
##
# #
###
Nieprawidłowy z powodu odłączenia:
#
# #
#
Prawidłowy wielokąt maksymalnego obwodu:
# #
# #
###
Kredyty
Początkowo nie doceniałem, jak szybko można obliczyć wartość maksymalnego obwodu, i zamierzałem po prostu poprosić o tę wartość jako wynik. Dzięki cudownie pomocnym osobom na czacie za wyjaśnienie, jak obliczyć maksymalny obwód dla arbitralnych liczb N i M, i pomóc przekształcić to w wyzwanie, które przetrwa więcej niż jedną odpowiedź ...
W szczególności dzięki:
Sparr , Zgarb , feersum , jimmy23013 .
Odpowiedzi:
CJam, 47 bajtów
Wypróbuj online
Wyjaśnienie:
Istnieją dwa główne przypadki wyniku. Jeśli co najmniej jeden z rozmiarów jest nieparzysty, wzór jest prostym „prowizją”. Na przykład dla danych wejściowych
7 6
:Jeśli oba rozmiary są równe, istnieje dodatkowa kolumna, w której co drugi kwadrat jest włączony. Na przykład dla danych wejściowych
8 6
:Teraz, aby pokazać, że te wzory osiągają teoretyczne maksimum obwodu, jak podano w opisie problemu, musimy potwierdzić, że pierwszy wzór ma obwód
(M + 1) * (N + 1)
, a drugi tę samą wartość minus 1.Dla pierwszego wzoru mamy obwód
M
o nieparzystym wymiarze:M
dla górnej krawędzi.2
z boku górnego rzędu.(M - 1) / 2
do przerw między zębami.(M + 1) / 2
zęby o obwodzie2 * (N - 1) + 1
każdy.Daje to w sumie:
W drugim przypadku, gdy zarówno
M
aN
nawet, obwód sumuje się z:M
dla górnej krawędzi.2
z boku górnego rzędu.M / 2
dla open # w górnym rzędzie.M / 2
zęby o obwodzie2 * (N - 1) + 1
każdy dla zębów prostych.2 * (N / 2 - 1)
elementy obwodowe dla postrzępionych zębów .Dodając to wszystko razem:
źródło
Ruby, Rev 1, 66
Wykorzystano podniesienie
m
do potęgi 0 o 1, aby zdecydować, czy 1 lubm
#
's zostaną wydrukowane.Służy
>
do testowania ostatniego wiersza zamiast==
.Nie można pozbyć się miejsca po putach ani nawiasów!
Ruby, Rev 0, 69
To anonimowa funkcja lambda. Użyj tego w ten sposób:
W końcu, po zapytaniu, czy M i N mogą być zamienione, nie potrzebowałem tego.
Typowe wyjścia dla N nieparzystych. Jeśli usuniemy
#
je po prawej stronie, oczywiście będziemy mieli (N + 1) (M + 1). Włączenie ich do kształtu usuwa 2 kwadraty z obwodu poziomego i dodaje 2 kwadraty z obwodu pionowego, więc nie ma zmian.Tutaj polegamy na wyrażeniu,
"#"*(i%2==0?m:1)
które daje naprzemienne rzędy#
symboli M i jednego#
symbolu, i odpowiednio uzasadnia M. znaki.Typowe wyjścia nawet dla N.
5 6
wyraźnie ma ten sam obwód6 5
lub przyrost M + 1 = 6 w porównaniu z5 5
dodaniem pionowego obwodu ze względu na crenelację dolnego rzędu.6 6
ma to samo co6 5
plus przyrost (M + 1) -1 = 6 na obwodzie pionowym. Zatem są one zgodne ze wzorem.Bardzo przydatne jest to, że Ruby
rjust
pozwala określić dopełnienie, które ma być używane dla pustych komórek. Zwykle wypełnienie jest ustawione na," "
ale dla ostatniego rzędu przełączamy się na"# "
(pamiętaj, że wypełnienie będzie potrzebne tylko w ostatnim rzędzie, jeśli N. jest parzyste. Gdy N jest nieparzyste, ostatni rząd będzie pełny i nie będzie żadnego uzasadnienia, więc nie zobaczę crenelacji).Sprawdź to tutaj.
źródło
i%2==0
na,i%2<1
aby zapisać bajt (dokonałem tej zmiany w linku ideone).#
wypełnienia do ostatniego rzędu? Na przykład, na ostatnim rysunku, czy obwód nie jest taki sam bez#
prawego dolnego rogu?#
po prostu dlatego, że jest już tak, jak każda linia jest zakończona, więc jest mniej bajtów niż wstawienie spacji. (Chociaż nie znam rubinu ...)."# "
nie jest" #"
spowodowane tym, że ten ostatni dałby 2 sąsiadujące#
za nieparzyste M, co zdecydowanie nie jest pożądane. 2 sąsiadujące#
nawet dla M nie szkodzi, więc poszedłem z tym. Nie próbowałemljust
, być może można to zrobić w bardziej przejrzysty sposób, ale nie byłoby tak oczywiste, że drukuję dokładnie M znaków na wiersz.C,
10997 bajtów i dowód poprawnościPisałem swoje rozwiązanie, ale @steveverrill mnie pobiło. Myślałem, że podzielę się tym samym, ponieważ dołączyłem dowód poprawności zastosowanej strategii.
Kod zredukowany:
Przed redukcją:
Strategia i dowód:
Zakładając poprawność równania maksymalnego ogranicznika (M + 1) (N + 1) - ((M + 1) (N + 1)) mod 2 , poniżej wyjaśniono zastosowaną optymalną strategię i udowodniono jej poprawność przez indukcję:
W przypadku nieparzystego M rysujemy kształt dłoni za pomocą palców M / 2 + 1, na przykład:
Udowadniamy teraz, że ta strategia jest optymalna dla wszystkich nieparzystych M przez indukcję:
Przypadek podstawowy: M = N = 1
Pojedyncza komórka jest wypełniona. Rozwiązanie jest poprawne, ponieważ (1 + 1) * (1 + 1) = 2 * 2 = 4, a kwadrat ma 4 boki.
Indukcja szerokości:
Załóżmy, że strategia kształtu dłoni działa dla (N, M-2), gdzie M jest nieparzysta, to znaczy, że jej obwód jest optymalny i wynosi (N + 1) (M - 2 + 1) + ((M -1) (N + 1)) mod 2 . Teraz pokazujemy, że będzie działać dla (N, M) .
Proces dodawania palca usuwa jedną krawędź z wielokąta i dodaje 3 + 2N . Na przykład:
Łącząc to z naszą hipotezą, że poprzedni obwód był optymalny, nowy obwód jest:
Ponieważ mamy do czynienia z arytmetyką modulo 2,
W ten sposób udowodnienie, że zwiększenie szerokości przez dodanie palców prowadzi do optymalnego obwodu.
Indukcja na wysokości:
Załóżmy, że strategia kształtu dłoni działa dla (N-1, M) , gdzie M jest nieparzysta, to znaczy, jej obwód jest optymalny i jest to N (M + 1) + ((M + 1) N) mod 2 . Teraz pokazujemy, że będzie działać dla (N, M) .
Zwiększenie wysokości ręki jedynie wydłuża palce, znajdujące się na pierwszym i co drugim indeksie x. Z każdym wzrostem wysokości każdy palec dodaje dwa do obwodu i są (M + 1) / 2 palce, a zatem wzrost N prowadzi do wzrostu o 2 (M + 1) / 2 = M + 1 w obwód.
Łącząc to z hipotezą, mamy nowy obwód:
Arytmetyka modułowa pozwala nam uprościć ostatni termin, dzięki czemu uzyskujemy:
Udowodnienie, że rozwiązanie jest optymalne dla wszystkich N> 0 i nieparzystych M> 0.
W przypadku parzystej litery M wypełniamy planszę tak samo, jak w przypadku nieparzystej litery M, ale dodajemy crenelacje do ostatniego segmentu, na przykład:
Udowadniamy teraz, że ta strategia jest optymalna.
Indukcja dla parzystego M:
Załóżmy, że rozwiązanie jest poprawne dla (N, M-1), z nieparzystym M-1 (jak udowodniono w ostatnim przypadku), który ma optymalny obwód (N + 1) M - ( M (N + 1)) mod 2 . Teraz pokazujemy, że będzie działać dla (N, M).
Podobnie jak zwiększenie palców, każde crenelacja dodaje dwa do obwodu wielokąta. Całkowita liczba crenelacji wynosi (N + N mod 2) / 2 , dla sumy dodanego obwodu N + N mod 2 .
Łącząc to z hipotezą, mamy nowy obwód:
Mamy to
Ponieważ jeśli N jest nieparzyste, to zmniejsza się do 0 = 0, a jeśli N jest parzyste, zmniejsza się do
Zatem strategia jest optymalna dla wszystkich M, N> 0 .
źródło