/* Returns a version of 'key' where all numbers have been replaced by zeroes. If there were none, returns "". */ static QCString zeroKey( const char* key ) { QCString zeroed( strlen( key ) + 1 ); char *z = zeroed.data(); int i = 0, j = 0; int len; bool metSomething = FALSE; while ( key[i] != '\0' ) { len = numberLength( key + i ); if ( len > 0 ) { i += len; z[j++] = '0'; metSomething = TRUE; } else { z[j++] = key[i++]; } } z[j] = '\0'; if ( metSomething ) return zeroed; else return ""; }
/* Returns a version of 'key' where all numbers have been replaced by zeroes. If there were none, returns "". */ static QByteArray zeroKey( const char *key ) { QByteArray zeroed; zeroed.resize( int(strlen(key)) + 1 ); char *z = zeroed.data(); int i = 0, j = 0; int len; bool metSomething = false; while ( key[i] != '\0' ) { len = numberLength( key + i ); if ( len > 0 ) { i += len; z[j++] = '0'; metSomething = true; } else { z[j++] = key[i++]; } } zeroed.resize(j); if ( metSomething ) return zeroed; else return ""; }
int isPalindrome(int number) { int length = numberLength(number); int result = 1; for(int i = 1; i <= length / 2; i++) { if(digitOnNthPosition(number, i) != digitOnNthPosition(number, length + 1 - i)) { result = 0; break; } } return result; }
void test() { unsigned int numbers[] = {1,40,99,100,101,500,998,999,1000,1001}; mpz_t n; mpz_init(n); for (int i = 0; i < 30; i++) { mpz_set_ui(n, i); printf("isPrime(%d)==%d\n", i, isPrime(n)); } for (int i = 0; i < sizeof(numbers) / sizeof(numbers[0]); i++) { mpz_set_ui(n, numbers[i]); printf("isnumberLength(%d)==%d\n", numbers[i], numberLength(n)); } mpz_set_ui(n, 3797); printf("isTruncatableRight(3797)==%d\n", isTruncatableRight(n)); mpz_set_ui(n, 3797); printf("isTruncatableLeft(3797)==%d\n", isTruncatableLeft(n)); }
unsigned int isTruncatableLeft(mpz_t n) { unsigned int len = numberLength(n); mpz_t value, power; mpz_init(value); mpz_init(power); mpz_set(value, n); mpz_set_ui(power, 1); for (unsigned int i = 1; i < len; i++) mpz_mul_ui(power, power, 10); while (mpz_cmp_ui(power, 0) > 0) { //printNumber("left ", value, ", power "); //printNumber("", power, "\n"); if (!isPrime(value)) return 0; mpz_mod(value, value, power); mpz_tdiv_q_ui(power, power, 10); } return 1; }
static QString translationAttempt( const QString& oldTranslation, const char* oldSource, const char* newSource ) { int p = zeroKey( oldSource ).contains( '0' ); int oldSourceLen = qstrlen( oldSource ); QString attempt; QStringList oldNumbers; QStringList newNumbers; QMemArray<bool> met( p ); QMemArray<int> matchedYet( p ); int i, j; int k = 0, ell, best; int m, n; int pass; /* This algorithm is hard to follow, so we'll consider an example all along: oldTranslation is "XeT 3.0", oldSource is "TeX 3.0" and newSource is "XeT 3.1". First, we set up two tables: oldNumbers and newNumbers. In our example, oldNumber[0] is "3.0" and newNumber[0] is "3.1". */ for ( i = 0, j = 0; i < oldSourceLen; i++, j++ ) { m = numberLength( oldSource + i ); n = numberLength( newSource + j ); if ( m > 0 ) { oldNumbers.append( QCString( oldSource + i, m + 1 ) ); newNumbers.append( QCString( newSource + j, n + 1 ) ); i += m; j += n; met[k] = FALSE; matchedYet[k] = 0; k++; } } /* We now go over the old translation, "XeT 3.0", one letter at a time, looking for numbers found in oldNumbers. Whenever such a number is met, it is replaced with its newNumber equivalent. In our example, the "3.0" of "XeT 3.0" becomes "3.1". */ for ( i = 0; i < ( int ) oldTranslation.length(); i++ ) { attempt += oldTranslation[i]; for ( k = 0; k < p; k++ ) { if ( oldTranslation[i] == oldNumbers[k][matchedYet[k]] ) matchedYet[k]++; else matchedYet[k] = 0; } /* Let's find out if the last character ended a match. We make two passes over the data. In the first pass, we try to match only numbers that weren't matched yet; if that fails, the second pass does the trick. This is useful in some suspicious cases, flagged below. */ for ( pass = 0; pass < 2; pass++ ) { best = p; // an impossible value for ( k = 0; k < p; k++ ) { if ( ( !met[k] || pass > 0 ) && matchedYet[k] == ( int ) oldNumbers[k].length() && numberLength( oldTranslation.latin1() + ( i + 1 ) - matchedYet[k] ) == matchedYet[k] ) { // the longer the better if ( best == p || matchedYet[k] > matchedYet[best] ) best = k; } } if ( best != p ) { attempt.truncate( attempt.length() - matchedYet[best] ); attempt += newNumbers[best]; met[best] = TRUE; for ( k = 0; k < p; k++ ) matchedYet[k] = 0; break; } } } /* We flag two kinds of suspicious cases. They are identified as such with comments such as "{2000?}" at the end. Example of the first kind: old source text "TeX 3.0" translated as "XeT 2.0" is flagged "TeX 2.0 {3.0?}", no matter what the new text is. */ for ( k = 0; k < p; k++ ) { if ( !met[k] ) attempt += QString( " {" ) + newNumbers[k] + QString( "?}" ); } /* Example of the second kind: "1 of 1" translated as "1 af 1", with new source text "1 of 2", generates "1 af 2 {1 or 2?}" because it's not clear which of "1 af 2" and "2 af 1" is right. */ for ( k = 0; k < p; k++ ) { for ( ell = 0; ell < p; ell++ ) { if ( k != ell && oldNumbers[k] == oldNumbers[ell] && newNumbers[k] < newNumbers[ell] ) attempt += QString( " {" ) + newNumbers[k] + QString( " or " ) + newNumbers[ell] + QString( "?}" ); } } return attempt; }