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"와 두 개의 배열을 구성합니다. 첫 번째 배열은 문자열에서 널 종료 자로 설정할 문자를 나타내고 두 번째 배열은 문자열에서 어떤 문자가 첫 번째 문자 여야하는지 나타냅니다. 이 배열에는 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에서 재 해석 알고리즘을 효율적으로 구현하는 문제였습니다. 슬프게도 이중 유형을 사용해야했고 정확히 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
편집 : 불행히도 원시 배열을 사용하는 것이 실제로 더 짧으므로 코드가 훨씬 간단 해집니다. 그럼에도 불구하고 줄 슬라이싱은 재미있었습니다. 이론적으로 적절한 논증은 실제로 약간의 수학으로 올바른 조각을 내놓을 수 있습니다.