2019-01-26 Daily Challenge
What I've done today is Truncatable primes in Rust and Student Attendance Record II in JavaScript.
Math
Problem
Truncatable primes
Problem 37
The number 3797 has an interesting property. Being prime itself, it is possible to continuously remove digits from left to right, and remain prime at each stage: 3797, 797, 97, and 7. Similarly we can work from right to left: 3797, 379, 37, and 3.
Find the sum of the only eleven primes that are both truncatable from left to right and right to left.
NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes.
Solution
Nothing to say.
Implementation
extern crate primal;
use primal::Sieve;
fn main() {
const LIMIT: usize = 1_000_000_000;
let sieve: Sieve = Sieve::new(LIMIT);
let mut ans = 0;
let mut cnt = 0;
let mut i = 1;
while cnt < 11 {
let tmp = sieve.nth_prime(i);
if is_truncatable(tmp, &sieve) {
ans += tmp;
cnt += 1;
println!("{}", tmp)
}
i += 1;
}
println!("Answer is {}", ans);
}
fn is_truncatable(n: usize, sieve: &Sieve) -> bool {
let l = n.to_string().len();
if l == 1 {
return false;
}
let mut base = 10usize.pow(l as u32 - 1);
while base != 1 {
// println!("{}",n%base);
if !sieve.is_prime(n % base) {
return false
}
base /= 10;
}
let mut n = n;
while n != 0 {
// println!("{}",n);
if !sieve.is_prime(n) {
return false;
}
n /= 10;
}
true
}
Algorithm
Problem
552. Student Attendance Record II
Given a positive integer n, return the number of all possible attendance records with length n, which will be regarded as rewardable. The answer may be very large, return it after mod 109 + 7.
A student attendance record is a string that only contains the following three characters:
- 'A' : Absent.
- 'L' : Late.
- 'P' : Present.
A record is regarded as rewardable if it doesn't contain more than one 'A' (absent) or more than two continuous 'L' (late).
Example 1:
Input: n = 2
Output: 8
Explanation:
There are 8 records with length 2 will be regarded as rewardable:
"PP" , "AP", "PA", "LP", "PL", "AL", "LA", "LL"
Only "AA" won't be regarded as rewardable owing to more than one absent times.
Note: The value of n won't exceed 100,000.
Solution
There is a DP problem.
Let set a array $DP[n][6]$,where:
$DP[n][0]$ means no Absent and no Late at last of record,
$DP[n][1]$ means no Absent and one Late at last of record,
$DP[n][2]$ means no Absent and two Late at last of record,
$DP[n][3]$ means one Absent and no Late at last of record,
$DP[n][4]$ means one Absent and one at last of record,
$DP[n][5]$ means one Absent and two at last of record,
so,
$$DP[i][0] = \left{\begin{matrix} 1,i=1\\sum_{j=0}^2DP[i-1][j],i>1\end{matrix}\right.$$
$$DP[i][1] = \left{\begin{matrix} 1,i=1\DP[i-1][0],i>1\end{matrix}\right.$$
$$DP[i][2] = \left{\begin{matrix} 1,i=1\DP[i-1][1],i>1\end{matrix}\right.$$
$$DP[i][3] = \left{\begin{matrix} 1,i=1\\sum_{j=0}^5DP[i-1][j],i>1\end{matrix}\right.$$
$$DP[i][4] = \left{\begin{matrix} 1,i=1\DP[i-1][3],i>1\end{matrix}\right.$$
$$DP[i][5] = \left{\begin{matrix} 1,i=1\DP[i-1][4],i>1\end{matrix}\right.$$
Implementation
/**
* @param {number} n
* @return {number}
*/
var checkRecord = function(n) {
const MOD = 1000000007;
let dp = [];
dp.push([1, 1, 0, 1, 0, 0]);
dp.push([0, 0, 0, 0, 0, 0]);
for (let i = 1; i < n; ++i) {
dp[i & 1][0] = (dp[(~i) & 1][0] + dp[(~i) & 1][1]) % MOD;
dp[i & 1][0] = (dp[i & 1][0] + dp[(~i) & 1][2]) % MOD;
dp[i & 1][1] = dp[(~i) & 1][0];
dp[i & 1][2] = dp[(~i) & 1][1];
dp[i & 1][3] = 0;
for (let j = 0; j < 6; ++j) {
dp[i & 1][3] += dp[(~i) & 1][j];
dp[i & 1][3] %= MOD;
}
dp[i & 1][4] = dp[(~i) & 1][3];
dp[i & 1][5] = dp[(~i) & 1][4];
}
let ans = 0;
for (let i = 0; i < 6; ++i) {
ans += dp[(~n) & 1][i];
ans %= MOD;
}
return ans;
};