Istnieje wiele różnych sposobów wyjaśnienia mnożenia macierzy. Będę trzymać jedną cyfrę, ponieważ uważam, że większość ludzi tutaj jest z nią zaznajomiona (a ta liczba jest bardzo opisowa). Jeśli potrzebujesz bardziej szczegółowych informacji, sugeruję odwiedzić artykuł w Wikipedii lub wyjaśnienie na temat WolframMathWorld .
Proste wyjaśnienie:
Załóżmy, że masz dwie macierze, A i B , gdzie A to 3 na 2, a B to 2 na 3. Jeśli wykonasz mnożenie macierzy na tych macierzach, AB lub BA , otrzymasz wyniki poniżej:
Wyzwanie:
Zaimplementuj symboliczne mnożenie macierzy w swoim języku. Jako dane wejściowe weźmiesz dwie macierze, gdzie każdy element w macierzach jest reprezentowany przez znak ASCII niebiałej spacji (punkty kodowe 33-126). Musisz wyprowadzić iloczyn tych macierzy.
Zasady dotyczące wyników:
Iloczyn dwóch pozycji nie może zawierać żadnych symboli. To ab
, nie a*b
, a·b
, times(a,b)
lub coś podobnego. To aa
nie a^2
.
Suma warunków powinna zawierać spację (punkt 32 kodu ASCII) pomiędzy nimi. To a b
, nie a+b
, plus(a,b)
lub coś podobnego.
Uzasadnieniem dla tych dwóch zasad jest: Wszystkie znaki niebiałe spacje są dozwolone jako symbole w macierzach, dlatego używanie ich jako symboli matematycznych byłoby bałaganem. Więc to, co normalnie możesz napisać, a*b+c*d
jakie będzie ab cd
.
Możesz wybrać kolejność warunków. ab cd
, dc ab
I cd ba
są matematycznie rzecz biorąc takie same, więc można wybrać kolejność tu. Kolejność nie musi być spójna, o ile jest matematycznie poprawna.
Zasady dotyczące formatowania macierzy:
Macierz można wprowadzić w dowolnym formacie, z wyjątkiem pojedynczego ciągu bez ograniczników między wierszami (dzieje się tak, ponieważ dane wyjściowe zostałyby całkowicie pomieszane). Obie macierze muszą być wprowadzane w tym samym formacie. Wszystkie poniższe przykłady są prawidłowymi sposobami wprowadzania i wysyłania macierzy.
"ab;cd" <- This will look awful, but it's still accepted.
"a,b\nc,d"
[[a,b],[c,d]]
[a, b]
[c, d]
Wiem, że pozwala to na wiele formatów, które będą wyglądały na bałagan, ale wyzwanie polega na pomnożeniu macierzy, a nie na sformatowaniu danych wyjściowych.
Główne zasady:
- Możesz założyć prawidłowe dane wejściowe. Mnożenie macierzy zawsze będzie możliwe przy podanych wymiarach.
- Będą tylko dwie matryce.
- Możesz założyć, że macierze nie są puste
- Wbudowane funkcje są akceptowane (ale prawdopodobnie nieco kłopotliwe ze względu na wymagania dotyczące formatowania).
- Możesz oczywiście użyć znaków zmiany znaczenia w danych wejściowych, jeśli to konieczne (
\'
zamiast'
). - Każda standardowa metoda wejścia i wyjścia jest OK .
Przypadki testowe:
Dwie macierze wejściowe są pokazane z pustą linią pomiędzy nimi. Dane wyjściowe są wyświetlane po Output:
. Kiedy są dwie macierze wyjściowe, to po prostu pokazują inne wyjściowe, które zostałyby zaakceptowane.
Przypadek testowy nr 1
Inputs:
[a]
[b]
Output:
[ab]
[ba] <- Also OK
Przypadek testowy nr 2
Inputs:
[a, b]
[1, 4]
[y, {]
[%, 4, 1]
[a, b, c]
Output:
[a% ba, a4 bb, a1 bc]
[1% 4a, 14 4b, 11 4c]
[y% {a, y4 {b, y1 {c]
Przypadek testowy nr 3:
Inputs:
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 1, 2, 3]
[4, 5, 6, 7]
[a]
[b]
[c]
[d]
Output:
[1a 2b 3c 4d]
[5a 6b 7c 8d]
[9a 1b 2c 3d]
[4a 5b 6c 7d]
[d4 c3 b2 a1] <-- Also OK
[d8 c7 b6 a5]
[1b 9a c2 3d]
[a4 b5 d7 6c]
Jeśli twoją odpowiedzią na zasady dotyczące wymagania ab cd
zamiast a*b+c*d
jest: powinieneś unikać uciążliwych formatów wejścia / wyjścia , to chciałbym zauważyć, że formaty wejścia i wyjścia są bardzo elastyczne. Fakt, że nie można używać *
i +
dla produktów i kwot może utrudnić użyć prostego wbudowany, ale nie uważam, że nic negatywnego.
źródło
Odpowiedzi:
Haskell ,
6261 bajtówWypróbuj online! Przykładowe użycie:
Znalazłem sposób na uzyskanie
transpose
funkcji o jeden bajt krócej niż przy użyciu importu:Stara wersja z importem: (62 bajty)
Wypróbuj online!
Jest bardzo podobna do mojej odpowiedzi na nie-symbolicznym mnożenia macierzy :
a!b=[sum.zipWith(*)r<$>transpose b|r<-a]
, zastępując mnożenie(*)
sznurkiem konkatenacji(++)
isum
zunwords
których skleja listę ciągów z przestrzeni pomiędzy. Import jest potrzebny dla tejtranspose
funkcji, więc w sumie transpozycja drugiej macierzy zużywa połowę bajtów ...Stara wersja bez importu: (64 bajty)
Wypróbuj online!
Ponieważ import i
transpose
funkcja zajmują tak dużo bajtów, próbowałem rozwiązać zadanie bez importu. Jak dotąd podejście to okazało się dwa bajty dłuższe, ale może być bardziej grywalne. Edycja: inne podejście u góry wygrywa z importem!Zrozumienie listy
[s:t|_:s:t<-b]
pobiera niepuste ogony z listb
, użycie tylko,[t|_:t<-b]
aby uzyskać ogony, byłoby o 4 bajty krótsze (nawet w porównaniu z wersją importu), ale dołącza pusty wiersz, podobnie jak["","",""]
macierz, która, jak sądzę, jest niedozwolona.źródło
Mathematica, 36 bajtów
Inner
jest uogólnieniem MathematikiDot
(tj. zwykłym produktem macierzy / wektora). Uogólnia iloczyn kropkowy, umożliwiając zapewnienie dwóch funkcjif
ig
, które będą używane zamiast zwykłego mnożenia i dodawania, odpowiednio. Zamieniamy mnożenie na#<>#2&
(które łączy dwa znaki w jeden ciąg) i dodawanie naStringRiffle@*List
, które najpierw otacza wszystkie sumy na liście, a następnieStringRiffle
łączy je spacjami.Można potencjalnie użyć
Dot
operatora,.
a następnie przekształcić wynik, ale problem polega na tym, że takie rzeczy"a"*"a"
natychmiast przekształcą się w"a"^2
(to samo w przypadku sum), co byłoby denerwujące, aby rozdzielić je ponownie.źródło
Rubin, 61 bajtów
Przykładowy przebieg:
źródło
Clojure, 53 bajty
Uruchamianie z argumentami
[["a" "b"]["c" "e"]]
i[["f" "g"]["h" "i"]]
zwrotami((("af" "bh") ("ag" "bi")) (("cf" "eh") ("cg" "ei")))
. Jest to w rzeczywistości krótsza wersja numeryczna .źródło
Dyalog APL , 10 bajtów
Pobiera macierze znaków jako argumenty lewy i prawy. Zwraca macierz list znaków. (APL reprezentuje ciągi jako listy znaków.)
Wypróbuj APL online!
Normalny produkt wewnętrzny znajduje się w APL
+.×
, ale dodawanie i mnożenie może być dowolnymi funkcjami, w szczególności:Dodawanie zostało zastąpione przez
{
anonimową funkcję:∊
spłaszczona⍺ ' ' ⍵
lista składająca się z lewego argumentu, spacji i prawego argumentu⍵
}
Mnożenie zostało zastąpione konkatenacją,
,
źródło
Galaretka , 7 bajtów
To diademiczne łącze, które przyjmuje B i A jako argumenty (w tej kolejności) i zwraca AB . Dane wejściowe i wyjściowe mają postać tablic 2D ciągów, które w rzeczywistości są tablicami znaków 3D. Kolejny bajt można zapisać, przyjmując tablice znaków 2D jako dane wejściowe. Nie jestem pewien, czy to dozwolone.
Wypróbuj online!
Trudno jest ustalić, co Jelly robi pod maską, gdy w grę wchodzą sznurki, ponieważ przed drukowaniem robi się dużo rozpryskiwania. W ten sposób Jelly reprezentuje dane wejściowe i wyjściowe wewnętrznie.
Jak to działa
źródło
Prolog,> 256 bajtów
Używam {_ | _}, który jest findall / 3, _ [_, _], który jest arg / 3 i suma (_), która jest agregacją. Wszystkie mogą być używane w środku to / 2:
Wraz z dodatkowymi definicjami dla wyżej wymienionych predykatów i niestandardowym jest / 2, który może zwrócić więcej niż liczby, jego pewność> 256 bajtów.
źródło
JavaScript (ES6), 65 bajtów
Pobiera dane wejściowe jako dwie tablice znaków 2D i zwraca tablicę ciągów 2D. Dodaj 10 bajtów do obsługi danych wejściowych jako dwie tablice 1D łańcuchów.
źródło
Pyth, 14 bajtów
Program, który pobiera dwie dwuwymiarowe listy znaków oddzielone znakiem nowej linii i drukuje dwuwymiarową listę ciągów znaków.
Zestaw testowy
Jak to działa
[Wyjaśnienie nastąpi później]
źródło
Pip , 17 bajtów
Jest to funkcja, która pobiera dwie zagnieżdżone listy ciągów (jednoznakowych) i zwraca zagnieżdżoną listę ciągów. Wypróbuj online! (z dwoma testami).
Wyjaśnienie
Argumenty
{}
funkcji -delimitowanej są przypisywane do zmiennych lokalnycha
doe
. Pierwszy argument funkcji lambda jest reprezentowany przez_
.źródło