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?-_:_]);}
इसे ऑनलाइन आज़माएं!
पुराना लेकिन शांत: सी (जीसीसी) , 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 से): अकोश, सिन्ह, असिन्ह, अतनह, तान, कोश, असिन, सिन, कॉस, अतन, तन, एको।
अब मैं सिर्फ तार की एक सूची में अनुक्रमण कर सकता था, लेकिन नाम बहुत लंबे और बहुत समान हैं, इसलिए इसके बजाय मैं उन्हें एक स्ट्रिंग के स्लाइस से बाहर निकालता हूं।
ऐसा करने के लिए, मैं स्ट्रिंग "एसिनहोसचटन" और दो सरणियों का निर्माण करता हूं। पहला सरणी इंगित करता है कि स्ट्रिंग में कौन सा वर्ण शून्य टर्मिनेटर पर सेट है, जबकि दूसरा इंगित करता है कि स्ट्रिंग में कौन सा वर्ण पहले वाला होना चाहिए। इन सरणियों में शामिल हैं: 10,5,5,0,14,10,4,4,9,14,0,9 और 5,1,0,10,11,6,0,1,6,10,11, क्रमशः ५।
अंत में यह केवल सी में कुशलता से पुनर्व्याख्या एल्गोरिथ्म को लागू करने का मामला था। अफसोस की बात है कि मुझे दोहरे प्रकार का उपयोग करना था, और ठीक 3 उपयोगों के साथ, यह सिर्फ double
तीन बार उपयोग करने के लिए तेज था फिर #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
संपादित करें: दुर्भाग्य से सिर्फ एक कच्चे सरणी का उपयोग करना वास्तव में कम है, इसलिए कोड बहुत सरल हो जाता है। फिर भी स्ट्रिंग स्लाइसिंग मजेदार थी। सिद्धांत रूप में एक उपयुक्त तर्क वास्तव में कुछ गणित के साथ अपने दम पर सही स्लाइस के साथ आ सकता है।