Ile prostokątów w siatce?


29

Cóż, chociaż wyzwanie to okazało się ogromnym sukcesem, okazało się również, że jego rozwiązanie było bardzo trywialne. Dlatego dla tych, którzy szukają większego wyzwania, stworzyłem kontynuację tego wyzwania, w którym musisz teraz policzyć liczbę unikalnych prostokątów. Sprawdź to!

Teraz, dla tych z Was, którzy chcą rozwiązać to wyzwanie, nadchodzi.


Cóż, tak naprawdę nie mamy takiego wyzwania, więc proszę bardzo.

Rozważ tę 3 x 3siatkę prostokątów:

Przykład

Ile jest prostokątów? Cóż, licząc wizualnie, widzimy, że w rzeczywistości są 36prostokąty, w tym cała płaszczyzna, wszystkie pokazane na animowanym pliku GIF poniżej:

Prostokąty w przykładzie

Zadanie

Liczenie prostokątów, jak pokazano powyżej, jest zadaniem. Innymi słowy, biorąc pod uwagę 2 całkowite większe niż lub równe 0, mi n, w których moznacza się szerokość i nreprezentuje wysokość, moc całkowitą liczbę prostokątów w tej m x nsiatce prostokątów.

Zasady

  • Zastosowanie jakichkolwiek wbudowanych rozwiązań, które bezpośrednio rozwiązują ten problem, jest wyraźnie zabronione.

  • Wyzwanie to nie polega na znalezieniu najkrótszej odpowiedzi, ale na znalezieniu najkrótszej odpowiedzi w każdym języku. Dlatego żadna odpowiedź nie zostanie zaakceptowana.

  • Standardowe luki są zabronione.

Przypadki testowe

Przedstawione w formacie Array of Integers Input -> Integer Output:

[0,0] -> 0
[1,1] -> 1
[3,3] -> 36 (Visualized above)
[4,4] -> 100
[6,7] -> 588

Referencje

Pamiętaj, to jest , więc wygrywa najkrótszy kod!


Obliczyłem 588dla ostatniego przypadku testowego.
Leaky Nun

@LeakyNun Cóż, więc myślę, że przegapiłem kilka, licząc je. Jest naprawione.
R. Kap

Jaka jest maksymalna wartość wejściowa?
Erik the Outgolfer

Odpowiedzi:


34

Python, 22 bajty

lambda m,n:m*~m*n*~n/4

Formuła m*n*(m+1)*(n+1)/4jest skracana za pomocą komplementu bitowego ~m=-(m+1), wyrażając (m+1)*(n+1)jako ~m*~n.

Dlaczego liczba prostokątów m*n*(m+1)*(n+1)/4? Każdy prostokąt jest określony przez wybór dwóch linii poziomych (góra i dół) i dwóch linii pionowych (lewa i prawa). Istnieją m+1linie poziome, z których wybieramy podzbiór dwóch odrębnych. Tak więc liczba wyborów jest taka choose(m+1,2), jaka jest m*(m+1)/2. Pomnożenie przez n*(n+1)/2wybór linii pionowych daje wynik.


Ta sztuczka +1 jest genialna.
David Ljung Madison Stellar

11

Galaretka , 4 bajty

RS€P

Wypróbuj online!

Alternatywnie, również 4 bajty

pP€S

Wypróbuj online!


Dobra robota. Kciuki w górę. :)
R. Kap

24
Chcesz to wyjaśnić?
Pureferret,

Istnieją również בHPi ‘c2Pbyć może inne 4 bajtowe alternatywy.
mile

1
@Pureferret używa wzoru z OEIS o co jest produktem nthi mthnumer trójkątnym. Rkonwertuje każdy numer w indeksie 1 opartego na: [1, 2, ..., n]. Sjest suma i oznacza „każdy”, więc każda lista jest sumowane, dając listę: [nth triangle number, mth triangle number]. Następnie Pbierze produkt z tej listy, co daje pożądany rezultat.
FryAmTheEggman

1
@FryAmTheEggman, więc co mówisz .... Magic
Pureferret


9

Mathematica, 15 bajtów

##(1##+##+1)/4&

Jest to funkcja bez nazwy, która przyjmuje dwa argumenty liczb całkowitych i zwraca liczbę prostokątów.

Wyjaśnienie

Implementacja jest zasadniczo bardzo golfową formą iloczynu dwóch trójkątnych liczb. Może warto przeczytać sekcję „Sekwencje argumentów” w tym poście, aby poznać szczegóły, ale postaram się streścić tutaj sedno.

##rozwija się do sekwencji wszystkich argumentów. Jest to podobne do rozpryskiwania w innych językach. Na przykład, jeśli argumentami są 3i 4, to {1, 2, ##, 5}da ci {1, 2, 3, 4, 5}. Ale to nie działa tylko na listach, ale w jakimkolwiek wyrażeniu, np. f[1, 2, ##, 5]Byłoby również f[1, 2, 3, 4, 5].

Staje się to interesujące, gdy łączysz się ##z operatorami. Wszystkie operatory w Mathematica są po prostu krótkimi rękami, aby uzyskać f[...]podobne wyrażenie (być może zagnieżdżone). Np. a+bJest Plus[a, b]i a-bfaktycznie reprezentuje Plus[a, Times[-1, b]]. Teraz, gdy łączysz się ##z operatorami, Mathematica najpierw rozszerza operatory, traktując je ##jak pojedynczy operand, i rozwija je tylko na końcu. Wstawiając ##w odpowiednie miejsca, możemy zatem użyć go zarówno do pomnożenia, jak i dodania operandów.

Zróbmy to dla powyższego kodu:

##(1##+##+1)/4

Po rozwinięciu do pełnej formy otrzymujemy:

Times[##, Plus[Times[1, ##], ##, 1], Rational[1/4]]

Wstawmy argumenty funkcji ai b:

Times[a, b, Plus[Times[1, a, b], a, b, 1], Rational[1/4]]

A teraz przekształcamy go z powrotem w standardowy zapis matematyczny:

a * b * (a * b + a + b + 1) / 4

Trochę przestawienia pokazuje, że jest to wynik liczb trójkątnych:

a * b * (a + 1) * (b + 1) / 4
(a * (a + 1) / 2) * (b * (b + 1) / 2)
T(a) * T(b)

Ciekawostka: ta implementacja jest tak Golfy, to ta sama długość jak wbudowany do obliczania jednego numeru trójkątny PolygonalNumber.


8

C, 25 bajtów

#define r(x,y)x*y*~x*~y/4

Wersja purystyczna (27):

r(x,y){return x*y*~x*~y/4;}

Wersja ISO (35):

#define r(x,y)((x)*(y)*~(x)*~(y)/4)

Którą wersję uważasz za najlepszą?
Erik the Outgolfer

8

Meduza , 16 bajtów

p|%/**+1
  4  Ei

Format wejściowy jest taki [x y], że wynik jest tylko wynikiem.

Wypróbuj online!

Alternatywne rozwiązanie, ta sama liczba bajtów:

pm%/*[*i
  4  +1

Wyjaśnienie

Czas, aby dać meduzom wstęp, na który zasługuje! :)

Meduza jest Zgarb język jest oparty na jego wyzwanie 2D, składnia . Semantyka jest w dużej mierze inspirowana przez J, ale składnia jest dziełem sztuki. Wszystkie funkcje są pojedynczymi znakami rozmieszczonymi na siatce. Funkcje pobierają argumenty od następnego tokena na południe i wschód od nich i zwracają wynik na północ i zachód. To pozwala ci stworzyć interesującą sieć wywołań funkcji, w których ponownie wykorzystujesz wartości, przekazując je do kilku funkcji z wielu kierunków.

Jeśli zignorujemy fakt, że niektóre tokeny w powyższym programie są operatorami specjalnymi (funkcje wyższego poziomu), powyższy program zostałby napisany mniej więcej tak:

p(|( /*(i*(i+1)) % 4 ))

Przejdźmy do kodu od dołu do góry. Dane wejściowe są zasilane przez i, który w związku z tym ocenia [x y].

Na +wierzchu otrzymuje to wejście wraz z literałem 1i dlatego zwiększa oba elementy, aby dać [(x+1) (y+1)](większość operacji jest automatycznie dzielona na listy).

Druga wartość ijest wysyłana w lewo, ale Epodziały to argument wschodni na północ i zachód. Oznacza to, że wejścia na prawo *są w rzeczywistości [x y]i [(x+1) (y+1)]tak tego oblicza [x*(x+1) y*(y+1)].

Następny w *górę jest faktycznie modyfikowany przez poprzedni, /który zamienia go w operację składania. Złożenie *pary po prostu ją zwielokrotnia, więc otrzymujemy x*(x+1)*y*(y+1).

Teraz %jest tylko podział, więc oblicza x*(x+1)*y*(y+1)/4. Niestety skutkuje to liczbą zmiennoprzecinkową, więc musimy zaokrąglić ją za pomocą unarnego |. Na koniec podawana jest ta wartość, do pktórej wypisywany jest wynik końcowy.


Mógłbym przysiąc, że przeczytałem coś w dokumentacji na temat dzielenia liczb całkowitych ...
Conor O'Brien

7

R, 40 35 bajtów

Czas wskoczyć na głęboki koniec! Oto mój kod R , inspirowany odpowiedzią @xnor:

a=scan();(n=a[1])*(m=a[2])*(n+1)*(m+1)/4 

EDYCJA : W tej wersji R zapyta dwukrotnie o dane wejściowe.

(n=scan())*(m=scan())*(n+1)*(m+1)/4

cat(prod(choose(scan()+1,2)))ma 29 bajtów.
Giuseppe,

6

CJam, 12 10 bajtów

2 bajty zapisane dzięki Martinowi.

{_:)+:*4/}

Wypróbuj online!

Jest to blok, który pobiera listę 2 elementów ze stosu i pozostawia rozwiązanie na stosie. Użytkowa pełny program do testowania: riari+{_:)+:*4/}~.

Oparty na wyjątkowym rozwiązaniu Python dla xnor.

Wyjaśnienie:

{_:)+:*4/}
{        } -- Define a block
 _:)       -- Duplicate list, increment all values in new list
    +      -- Join the two lists
     :*    -- Fold multiply over all 4 elements
       4/  -- Divide by 4

2
Myślę, że to działa dla 10, jeśli wprowadzisz listę dwóch elementów? {_:~+:*4/}
Martin Ender

W rzeczywistości nie ma potrzeby używania ~w CJam. Po prostu użyj ).
Martin Ender,

5

Matlab, 23 19 bajtów

@(x)prod([x/2,x+1])

Implementacja formuły m*n*(m+1)*(n+1)/4
Zastosowanie:ans([m,n])


4

MATL , 6 bajtów

tQ*2/p

Dane wejściowe to tablica formularza [m,n].

Wypróbuj online!

Wyjaśnienie

Bezpośrednie obliczenia na podstawie formuły m*(m+1)*n*(n+1)/4.

t     % Input array [m,n] implicitly. Duplicate
Q     % Add 1 to each entry of the copy: gives [m+1,n+1]
*     % Multiply element-wise: gives [m*(m+1),n*(n+1)]
2/    % Divide each entry by 2: [m*(m+1)/2,n*(n+1)/2]
p     % Product of the two entries: m*(m+1)*n*(n+1)/4. Display implicitly


4

Java 7, 39 38 bajtów

int c(int a,int b){return~a*a*b*~b/4;}

Java 8, 26 25 19 18 17 bajtów

a->b->a*~a*b*~b/4

Na podstawie doskonałej odpowiedzi @xnor . Wiele bajtów zapisanych dzięki @DavidConrad . Wypróbuj tutaj.

Kod testowy (Java 7):

Wypróbuj tutaj.

class M{
  static int c(int a,int b){return~a*a*b*~b/4;}

  public static void main(String[] a){
    System.out.println(c(0, 0));
    System.out.println(c(1, 1));
    System.out.println(c(3, 3));
    System.out.println(c(4, 4));
    System.out.println(c(6, 7));
  }
}

Wydajność:

0
1
36
100
588

1
Nie potrzebujesz tego returni a->b->jest o jeden bajt krótszy niż (a,b)->.
David Conrad

2
Nie sądzę, żebyś potrzebował średnika, ponieważ jeśli przekazałeś lambda do metody, która przyjęła Function<Integer, Function<Integer, Integer>>jako parametr, nie pojawiłby się średnik.
David Conrad

2
Zgadzam się z @DavidConrad: Nie liczę zakończenia ;na pojedynczym wyrażeniu lambda J8.
97

@DavidConrad Przepraszam za bardzo późną edycję, ale dopiero teraz zauważyłem, że przeczytałem twój komentarz, aby usunąć return ... Ponadto, prawie nigdy nie programuję w Javie 8 (stąd wszystkie moje odpowiedzi w Javie 7), ale jak mam zacząć a->b->pracę? Oto ideon dla bieżącej sprawy.
Kevin Cruijssen

1
Przepraszam za bardzo późną odpowiedź! Trzeba curry funkcji, więc trzeba zmienić MathOperation.operationtylko jeden wziąć int, zwróci Function<Integer, Integer>, a gdy go nie nazywać, początkowo przechodzą tylko pierwszy parametr a, a następnie zadzwonić .apply(b)na Function. Musisz także zaimportować java.util.function.Function. Oto ideone ze zmianami.
David Conrad,

3

Ruby, 22 bajty

Kradnąc sztuczkę @ Xnora i robiąc dźgnięcie-lambda:

r=->(m,n){m*n*~m*~n/4}

Przykładowe wywołanie:

r[6,7]     # => 588

Lub jako proc, również 22 bajty:

proc{|m,n|m*n*~m*~n/4}

Które moglibyśmy następnie nazwać:

proc{|m,n|m*n*~m*~n/4}.call(6,7)     # => 588

Nie trzeba go nazywać - anonimowe funkcje są zgodne z konwencją witryny
Conor O'Brien

3

Labirynt , 13 11 bajtów

*?;*_4/!
):

Wypróbuj online!

Wyjaśnienie

To również oblicza iloczyn liczb trójkątnych, jak większość odpowiedzi. Wiodący blok 2x2 to mała pętla:

*?
):

Przy pierwszej iteracji *nic nie robi, więc prawdziwa kolejność pętli jest następująca:

?   Read integer N from STDIN or 0 at EOF and push onto stack. If 0, exit the loop.
:   Duplicate N.
)   Increment.
*   Multiply to get N*(N+1).

Pozostały kod jest po prostu liniowy:

;   Discard the zero that terminated the loop.
*   Multiply the other two values.
_4  Push a 4.
/   Divide.
!   Print.

Labirynt następnie próbuje wykonać /ponownie, co kończy program z powodu dzielenia przez zero.



2

05AB1E, 4 bajty

€LOP

Wyjaśnienie

Korzysta ze wzoru opisanego w A096948

      # Implicit input, ex: [7,6]
€L    # Enumerate each, [[1,2,3,4,5,6,7],[1,2,3,4,5,6]]
  O   # Sum, [28,21]
   P  # Product, 588
      # Implicit display

Przyjmuje dane jako [n, m] .

Wypróbuj online


1

Pyth, 8 6 bajtów

Dwa bajty zapisane dzięki @DenkerAffe.

*FmsSd

Dane wejściowe są oczekiwane jako lista podobna do [m,n]. Wypróbuj tutaj .

Wyjaśnienie:

          Implicit assignment of Q to eval(input).
*         Multiplication.
 F        Splat the following sequence onto the arguments of the previous function.
  m       Map the following function of d over Q (Q is implicitly added to the end).
   s      Reduce the following list with addition, initial value of 0.
    Sd    Return range(1,d+1).

1
Możesz użyć Fzamiast .*i usunąć, Qponieważ jest ona dodawana domyślnie.
Denker,

Wiedziałem o tym, Fale nie mogłem wymyślić, jak go używać i pomyślałem, że muszę go użyć .*... Dzięki!
Rhyzomatic


1

Lua, 74 63 bajtów

x,y=...n=0 for i=1,y do for j=i,i*x,i do n=n+j end end print(n)

Funkcja przyjmuje dane wejściowe jako parametry liczbowe.

Ze względu na sposób implementacji Lua jest to technicznie funkcja ze zmiennymi argumentami, którą można wywołać, zawijając ją w instrukcji „function” lub ładując ją z kodu źródłowego za pomocą „loadstring”


1
Widzę, że masz dość dużo kodu tylko dla I / O. Być może krótsze byłoby po prostu utworzenie funkcji, która pobierze dwie liczby i zwróci odpowiedź, i usunie cały ten niepotrzebny kod we / wy?
Zwei,

@Zwei Zapomniałem, że funkcje mogą pobierać dane wejściowe według parametrów. Dzięki za zwrócenie na to uwagi.
brianush1

Funkcję można nazwać czymś w rodzaju „f” zamiast całej nazwy „funkcja”, aby zaoszczędzić 7 dodatkowych bajtów
Zwei

W Lua słowo kluczowe „funkcja” jest wymagane do zadeklarowania funkcji. Jeśli nie podano nazwy (np. „Funkcja f ()”), jest to funkcja anonimowa. (np .: „function ()”). Dlatego „funkcja” jest wymagana do działania kodu.
brianush1

Och, zapomniałem, że lua tak działa. Mój błąd!
Zwei,


1

Brain-Flak , 84 80 bajtów

({}<>)({({})<({}[()])>}{})<>({({})<({}[()])>}{}[()]){<>(({}))<>({}[()])}<>({{}})

Wypróbuj online!

Prawdopodobnie bardzo nieoptymalny, szczególnie ze względu na ponowne użycie kodu w odniesieniu do liczb trójkątów, ale przynajmniej mamy rozwiązanie Brain-Flak, które działa.

Niestety wydaje się, że zawodzi, nieskończenie zapętlając się z przypadkiem 0 0testowym, ale wszystkie inne działają dobrze.




Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.