f (g (x)) maleje, podczas gdy g (f (x)) wzrasta

42

Aby sprostać temu wyzwaniu, musisz zaimplementować dwie liczby f i g na liczbach całkowitych, tak że f ∘ g jest funkcją ściśle malejącą, podczas gdy g ∘ f jest funkcją ściśle rosnącą. Innymi słowy, jeśli podejmują wszelkie dwóch liczb całkowitych a <b , to f (g (a))> f (g (b)) i g (f (a)) <g (f (b)) . Nie ma ograniczeń dotyczących f i g indywidualnie, z wyjątkiem tego, że muszą one mapować jedną liczbę całkowitą na inną liczbę całkowitą.

Podaj krótki opis f i g oraz argument, dlaczego mają wymaganą właściwość.

Kredyt: To wyzwanie zostało zainspirowane problemem w rumuńskim konkursie Master of Mathematics 2011 (który pyta o to samo, ale o liczby rzeczywiste zamiast liczb całkowitych). Jeśli naprawdę chcesz spoilerów, teraz wiesz, czego szukać.

Zasady

  • Słowo „funkcja” w tym wyzwaniu należy rozumieć matematycznie, odwzorowując jedną liczbę całkowitą na drugą: możesz albo napisać dwa programy lub dwie funkcje i użyć dowolnej ze standardowych metod odbierania danych wejściowych i dostarczania danych wyjściowych, jak zwykle. Możesz użyć ciągów reprezentujących liczby całkowite zamiast rzeczywistych zmiennych całkowitych, ale typy danych wejściowych i wyjściowych powinny być identyczne, aby funkcje można było komponować bez ręcznej konwersji typów pomiędzy nimi. Pamiętaj, że koncepcyjnie, f i g nadal muszą być funkcjami na ℤ, więc nie możesz oszukiwać, używając dwóch różnych reprezentacji ciągów o tej samej liczbie lub czegoś podobnego.

  • Pamiętaj, że funkcje mogą być nienazwane , o ile ich nazwa nie jest potrzebna sama lub inna funkcja, którą zdefiniujesz. Jeśli nazwiesz jedną lub obie funkcje, możesz założyć, że istnieją one w tym samym programie, aby mogły się nawzajem odwoływać w swojej implementacji (np. def f(x): return -g(x)W Pythonie).

  • Obowiązują zwykłe reguły przepełnienia liczb całkowitych: twoje rozwiązanie musi być w stanie pracować dla dowolnie dużych liczb całkowitych w hipotetycznej (lub być może rzeczywistej) wersji twojego języka, w której wszystkie liczby całkowite są domyślnie nieograniczone, ale jeśli twój program zawiedzie w praktyce z powodu implementacji brak obsługi liczb całkowitych tak dużych, co nie unieważnia rozwiązania.

  • Możesz używać dowolnego języka programowania , ale pamiętaj, że te luki są domyślnie zabronione.

  • To jest , więc twój wynik jest sumą liczby bajtów obu funkcji i wygrywa najkrótsza poprawna odpowiedź.

Martin Ender
źródło
Czy funkcje mogą zwracać ciąg znaków?
Matthew Roh
@SIGSEGV Powiedziałbym „tak”, ale tylko wtedy, gdy przyjmują one również ciąg znaków jako dane wejściowe, dzięki czemu można je komponować bez konieczności wstawiania jakiejkolwiek konwersji typu.
Martin Ender,
Aww darnit, próbowałem konwersji na ciąg znaków, aby inna funkcja nie mogła dalej edytować wyników.
Matthew Roh,
1
@Fatalize Correct. Każda musi być funkcją typu ℤ → ℤ.
Martin Ender,
1
@Bijan zarówno pozytywne, jak i negatywne.
Martin Ender,

Odpowiedzi:

18

Python, 68 znaków

f=lambda x:(1-x%2*2)*(2*x*x+(x<0))
g=lambda x:(1-x%2*2)*(2*x*x+(x>0))

f odwzorowuje liczby ujemne na liczby nieparzyste i liczby dodatnie na liczby parzyste, a liczby parzyste na liczby dodatnie i liczby nieparzyste na liczby ujemne, przy czym wielkość wyjściowa rośnie ściśle wraz z wielkością wejściową.

g robi to samo, z tym że odwzorowuje liczby ujemne na liczby parzyste i liczby dodatnie na liczby nieparzyste.

f ∘ g mapy ujemne → parzyste → dodatnie i dodatnie → nieparzyste → negatywne.
g ∘ f mapy ujemne → nieparzyste → negatywne i dodatnie → parzyste → pozytywne.

Dlatego f i g mają pożądane właściwości.

użytkownik1502040
źródło
2
fi gmogą być funkcjami nienazwanymi, więc możesz upuścić cztery bajty.
Martin Ender,
Możesz zdefiniować (1-x%2*2)jako zmienną, aby zapisać kilka bajtów.
OldBunny2800 10.04.17
Oto kompletny kod do zabawy import numpy as np; import matplotlib.pyplot as plt; xrange=np.arange(-3,4); f=lambda x:(1-x%2*2)*(2*x*x+(x<0)); g=lambda x:(1-x%2*2)*(2*x*x+(x>0)); plt.plot(xrange, map(f, xrange), 'ro'); plt.plot(xrange, map(g, xrange), 'go'); plt.plot(xrange, map(f, map(g, xrange)), 'b--'); plt.plot(xrange, map(g, map(f, xrange)), 'y--'); plt.show(); Możesz zastąpić ;go liniami dla czytelności.
Stéphane Gourichon
16

Python , 40 bajtów

f=lambda x:x*(-1)**x
g=lambda x:3*f(x)+1

Wypróbuj online! Niektóre dane wyjściowe są (-1)**(-3)zmiennoprzecinkowe, które są równe liczbom całkowitym, ponieważ dają na przykład zmiennoprzecinkowe.

Na podstawie pomysłów Petera Taylora . Funkcja fneguje liczby nieparzyste i pozostawia parzyste bez zmian. Funkcja grobi to samo, a następnie stosuje monotoniczną mapę z przełączaniem parzystości x -> 3*x + 1.

Od f(f(x)) = xtego czasu g(f(x)) = 3*f(f(x))+1 = 3*x+1rośnie.

Na f(g(x)) = f(3*f(x)+1)pomysł, że dokładnie jedna wewnętrzna i zewnętrzna fodwraca znak, dzięki czemu maleje.

  • Na parzyste x, f(x) = xale f(3*x+1) = -3*x-1dlatego , że 3*x+1jest dziwne.
  • Dla nieparzystych x, f(x) = -xa f(-3*x+1) = -3*x+1ponieważ -3*x+1jest parzysty.

Teraz potrzebujemy tylko parzystych i nieparzystych danych wejściowych przeplatanych w sposób malejący, co utrzymuje się, ponieważ -3*x±1zmniejsza się niezależnie od wyboru znaków. Dlatego 3*jest potrzebny.

Port Haskell ma 25 bajtów:

f x=x*(-1)**x
g x=1+3*f x

Wypróbuj online!

xnor
źródło
W Haskell (^)jest wykładnikiem liczb całkowitych.
user1502040 7.04.17
1
@ user1502040 Nie radzi sobie z wykładnikami ujemnymi.
xnor
1
Ponieważ nie nazywasz się gsobą, możesz zaoszczędzić dwa bajty, czyniąc go bezimiennym.
Martin Ender,
14

CJam (17 bajtów)

Funkcja f (nazwana, Fponieważ CJam dopuszcza tylko nazwy pisane dużymi literami):

{W1$2b,#*}:F

Funkcja g (anonimowa):

{F2*}

Demo online

Oszczędza to bajt, opierając się na szczegółach implementacji CJam, co jest prawdopodobnie błędem: podczas wykonywania podstawowych konwersji używa wartości bezwzględnej. 2b,dlatego podaje liczbę bitów w wartości bezwzględnej argumentu, więc f neguje dokładnie te liczby, których wartość bezwzględna ma nieparzystą liczbę bitów. g stosuje f, a następnie podwaja (zmieniając parzystość liczby bitów).

Zatem zastosowanie znaku f, a następnie g pozostawia znak niezmieniony i podwaja się, odwzorowując xna 2x. Zastosowanie g, a następnie f zmienia znak dokładnie raz i podwaja się, odwzorowując xna -2x.

Peter Taylor
źródło
Fajnie, to jest dokładnie rozwiązanie referencyjne podane w konkursie, z którego pochodzi. (Zakładam, że sam to wymyśliłeś?)
Martin Ender
@MartinEnder, widziałem już kiedyś ten problem. Prawdopodobnie na matematyce.
Peter Taylor,
2

Pyth, 34 bajtów

To jest tylko bezpośrednie tłumaczenie mojej odpowiedzi w języku Python.

*-1*2%Q2+*2*QQ<Q0
*-1*2%Q2+*2*QQ>Q0
użytkownik1502040
źródło