double d;_;f(double(*x)(double)){d=x(0.9247);_=*(int*)&d%12;puts((char*[]){"acosh","sinh","asinh","atanh","tan","cosh","asin","sin","cos","atan","tanh","acos"}[_<0?-_:_]);}
オンラインでお試しください!
古くてかっこいい:C(gcc)、194バイト
double d;_;f(double(*x)(double)){char n[]="asinhacoshatanh";d=x(0.9247);_=*(int*)&d%12;_=(_<0?-_:_);n[(int[]){10,5,5,0,14,10,4,4,9,14,0,9}[_]]=0;puts(n+(int[]){5,1,0,10,11,6,0,1,6,10,11,5}[_]);}
オンラインでお試しください!
-lm
TIO の切り替えは、単にテストすることです。
標準のトリガー関数の完全な実装を作成できれば、正しい答えが得られます。
説明
アイデアは、各トリガー関数の出力を整数として解釈するときに、12を法とする剰余が異なるような入力値を見つけることでした。これにより、配列インデックスとして使用できるようになります。
このような入力値を見つけるために、次のスニペットを作成しました。
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
// Names of trig functions
char *names[12] = {"sin","cos","tan","asin","acos","atan","sinh","cosh","tanh","asinh","acosh","atanh"};
// Pre-computed values of trig functions
double data[12] = {0};
#define ABS(X) ((X) > 0 ? (X) : -(X))
// Performs the "interpret as abs int and modulo by" operation on x and i
int tmod(double x, int i) {
return ABS((*(int*)&x)%i);
}
// Tests whether m produces unique divisors of each trig function
// If it does, it returns m, otherwise it returns -1
int test(int m) {
int i,j;
int h[12] = {0}; // stores the modulos
// Load the values
for (i = 0; i < 12; ++i)
h[i] = tmod(data[i],m);
// Check for duplicates
for (i = 0; i < 12; ++i)
for (j = 0; j < i; ++j)
if (h[i] == h[j])
return -1;
return m;
}
// Prints a nicely formatted table of results
#define TEST(val,i) printf("Value: %9f\n\tsin \tcos \ttan \n \t%9f\t%9f\t%9f\na \t%9f\t%9f\t%9f\n h\t%9f\t%9f\t%9f\nah\t%9f\t%9f\t%9f\n\n\tsin \tcos \ttan \n \t%9d\t%9d\t%9d\na \t%9d\t%9d\t%9d\n h\t%9d\t%9d\t%9d\nah\t%9d\t%9d\t%9d\n\n",\
val,\
sin(val), cos(val), tan(val), \
asin(val), acos(val), atan(val),\
sinh(val), cosh(val), tanh(val),\
asinh(val), acosh(val), atanh(val),\
tmod(sin(val),i), tmod(cos(val),i), tmod(tan(val),i), \
tmod(asin(val),i), tmod(acos(val),i), tmod(atan(val),i),\
tmod(sinh(val),i), tmod(cosh(val),i), tmod(tanh(val),i),\
tmod(asinh(val),i), tmod(acosh(val),i), tmod(atanh(val),i))
// Initializes the data array to the trig functions evaluated at val
void initdata(double val) {
data[0] = sin(val);
data[1] = cos(val);
data[2] = tan(val);
data[3] = asin(val);
data[4] = acos(val);
data[5] = atan(val);
data[6] = sinh(val);
data[7] = cosh(val);
data[8] = tanh(val);
data[9] = asinh(val);
data[10] = acosh(val);
data[11] = atanh(val);
}
int main(int argc, char *argv[]) {
srand(time(0));
// Loop until we only get 0->11
for (;;) {
// Generate a random double near 1.0 but less than it
// (experimentally this produced good results)
double val = 1.0 - ((double)(((rand()%1000)+1)))/10000.0;
initdata(val);
int i = 0;
int m;
// Find the smallest m that works
do {
m = test(++i);
} while (m < 0 && i < 15);
// We got there!
if (m == 12) {
TEST(val,m);
break;
}
}
return 0;
}
これを実行すると(-lmでコンパイルする必要があります)、値が0.9247の場合に一意の値が得られます。
次に、整数として再インターペットし、12を法として適用し、絶対値を取りました。これにより、各関数にインデックスが与えられました。それらは(0-> 11):acosh、sinh、asinh、atanh、tan、cosh、asin、sin、cos、atan、tanh、acosです。
これで、文字列の配列にインデックスを付けることができましたが、名前は非常に長く、非常に似ているため、代わりに文字列のスライスからそれらを取り出します。
これを行うには、文字列「asinhacoshatanh」と2つの配列を作成します。最初の配列は、文字列内のどの文字をヌルターミネータに設定するかを示し、2番目の配列は、文字列内のどの文字を最初の文字にするかを示します。これらの配列には、10,5,5,0,14,10,4,4,9,14,0,9および5,1,0,10,11,6,0,1,6,10,11が含まれます。それぞれ5。
最後に、Cで再解釈アルゴリズムを効率的に実装するだけでした。残念なことに、double型を使用する必要がありました。正確に3 double
回使用すると、3回使用#define D double\nDDD
してから2文字だけ使用する方が速くなりました。結果は上にあり、説明は下にあります。
double d;_; // declare d as a double and _ as an int
f(double(*x)(double)){ // f takes a function from double to double
char n[]="asinhacoshatanh"; // n is the string we will manipulate
int a[]={10,5,5,0,14,10,4,4,9,14,0,9}; // a is the truncation index
int b[]={5,1,0,10,11,6,0,1,6,10,11,5}; // b is the start index
d=x(0.9247); // d is the value of x at 0.9247
_=*(int*)&d%12; // _ is the remainder of reinterpreting d as an int and dividing by 12
_=(_<0?-_:_); // make _ non-negative
n[a[_]]=0; // truncate the string
puts(n+b[_]);} // print the string starting from the correct location
編集:残念ながら、生の配列を使用するだけで実際には短くなるため、コードははるかに単純になります。それにもかかわらず、文字列のスライスは楽しかったです。理論的には、適切な議論は実際にいくつかの数学で適切なスライスを思い付くかもしれません。