f(g(x))は減少し、g(f(x))は増加


42

この課題のために、f∘gは厳密に減少する関数であり、g∘fは厳密に増加する関数であるように、整数に2つの関数fgを実装する必要があります。つまり、任意の2つの整数a <bを取る場合、f(g(a))> f(g(b))およびg(f(a))<g(f(b))となります。fgに個別に制限はありませんが、それぞれが1つの整数を別の整数にマッピングする必要があることを除きます。

fgの簡単な説明と、それらに必要なプロパティがある理由の引数を含めてください。

クレジット:この課題は、2011年のルーマニアの数学修士大会(整数ではなく実数で求められます)の問題に触発されました。ネタバレが本当に必要な場合は、何を検索すればよいかがわかります。

ルール

  • この課題における「関数」という言葉は、1つの整数を別の整数にマッピングするという数学的な意味で解釈する必要があります。2つのプログラムまたは2つの関数を記述し、通常どおり入力を受け取り、出力を提供する標準的な方法を使用できます。実際の整数変数の代わりに整数の文字列表現を使用できますが、入力と出力のタイプは同一である必要があります。そのため、間にタイプを手動で変換することなく関数を構成できます。概念的には、fgはまだonの関数である必要があるため、同じ数字またはそのようなものの2つの異なる文字列表現を使用して不正行為を行うことはできません。

  • ことを忘れないでください関数は無名のかもしれ彼らの名は、それ自体またはユーザーが定義する別の機能で必要とされていない限り、。関数の一方または両方に名前を付ける場合、それらが同じプログラムに存在すると仮定して、それらの実装(def f(x): return -g(x)Pythonなど)で相互に参照できるようにします。

  • 通常の整数オーバーフロールールが適用されます。ソリューションは、すべての整数がデフォルトで制限されていない仮想バージョン(または実際のバージョン)の任意の大きな整数で動作できる必要がありますが、実装によりプログラムが実際に失敗する場合それほど大きな整数をサポートしていなくても、ソリューションは無効になりません。

  • 任意のプログラミング言語を使用できますが、これらの抜け穴はデフォルトでは禁止されています。

  • これはであるため、スコアは両方の関数のバイト数の合計であり、最短の有効な回答が勝ちます。


関数は文字列を返すことができますか?
マシュー盧

@SIGSEGVはいと言いますが、入力として文字列も使用する場合にのみ、タイプ変換を挿入することなく構成できます。
マーティンエンダー

Aww darnit、他の関数が結果をさらに編集できないように文字列に変換しようとしました。
マシュー盧

1
@Fatalize正しい。それぞれは、ℤ→ℤ型の関数でなければなりません。
マーティンエンダー

1
@Bijanは正と負の両方です。
マーティンエンダー

回答:


18

Python、68文字

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は、負の数値を奇数に、正の数値を偶数に、偶数を正の数値に、奇数を負の数値にマッピングします。出力の大きさは入力の大きさに応じて厳密に増加します。

gは、負の数を偶数に、正の数を奇数にマッピングすることを除いて同じことを行います。

f∘gは、負→偶数→正と正→奇数→負にマッピングします。
g∘fは、負→奇数→負および正→偶数→正にマッピングします。

したがって、fとgには望ましい特性があります。


2
fそしてg無名の関数にすることもできますので、あなたは4つのバイトをドロップすることができます。
マーティンエンダー

(1-x%2*2)数バイトを節約する変数として定義できます。
OldBunny2800

遊ぶための完全なコードは次のとおりです。読みやすく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(); するため;に改行に置き換えることができます。
ステファンGourichon

16

Python、40バイト

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

オンラインでお試しください!一部の出力は(-1)**(-3)、たとえば浮動小数点数を与えるため、整数に等しい浮動小数点数です。

Peter Taylorのアイデアに基づいています。この関数は、f奇数を無効にし、偶数を変更しません。関数gは同じことを行い、単調なパリティスイッチングマップを適用しますx -> 3*x + 1

以来f(f(x)) = xg(f(x)) = 3*f(f(x))+1 = 3*x+1増加しています。

以下のためにf(g(x)) = f(3*f(x)+1)、アイデアは、内側と外側のまさに一つでありf、それが減少すること、フリップサイン。

  • でものためにxf(x) = xしかし、f(3*x+1) = -3*x-1理由は3*x+1奇数です。
  • 奇数のためxf(x) = -xf(-3*x+1) = -3*x+1理由は-3*x+1さえあります。

偶数と奇数の入力インターリーブが減少する方法で必要になるだけです。これは-3*x±1、符号の選択方法に関係なく減少するためです。これが3*必要な理由です。

Haskellポートは25バイトです:

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

オンラインでお試しください!


Haskellでは、(^)整数の累乗です。
user1502040

1
@ user1502040負の指数を処理できません。
-xnor

1
g自分を呼び出していないので、名前を付けずに2バイト節約できます。
マーティンエンダー

14

CJam(17バイト)

関数f(FCJamは大文字の名前のみを許可するため、名前が付けられています):

{W1$2b,#*}:F

関数g(匿名):

{F2*}

オンラインデモ

これは、間違いなくバグであるCJamの実装の詳細に依存することでバイトを節約します。ベース変換を行うとき、絶対値を使用します。2b,したがって、引数の絶対値のビット数を与えるため、fは、絶対値のビット数が奇数である数値を正確に否定します。gはfを適用してから2倍にします(ビット数のパリティを変更します)。

したがって、fを適用してからgを適用すると、符号は変更されずに倍になり、にマッピングさx2xます。gを適用してからfを適用すると、符号が1回だけ変更されて2倍になり、にマッピングさx-2xます。


ニース、これはまさにこれが元のコンペティションで提供される参照ソリューションです。(私はあなたがそれを独自に思いついたと思いますか?)
マーティンエンダー

@MartinEnder、私は以前どこかでこの問題を見てきました。おそらくmath.SEで。
ピーターテイラー

2

Pyth、34バイト

これは、私のPythonの答えを直接翻訳したものです。

*-1*2%Q2+*2*QQ<Q0
*-1*2%Q2+*2*QQ>Q0
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.