PE1 (AY20/21)
Problems
1. Error*
Ignore most significant digits in num
Basic idea is to use num to modular . And here is the code for implementation:
For example, if we input ignore_last_k_digit(1234, 2)
, the power will be raised to 100 and we will get 1234 % 100 = 34
.
Ignore the least significant digits in num
The basic idea here is to use integer division, so we use .
For example, if we input ignore_first_k_digit(1234, 2)
, then power will be raised to 100
. So, we will return 1234 / 100 * 100
, which is 12 * 100 = 1200
.
2. Twilight
This is a "give-away" question.
3. Reverse*
Naive idea
The basic and and naive idea for this question is:
take the last digit of
reverse the rest of the digits of
put the last digit of "in front"
And the trickest part lies in how to put the last digit of in front? The basic idea is that if we know the digit position/ the number of digits (Let's say it's ), we can quickly put the digit in front by timing it with . So now, we need to write another recursive function that can help us calculate the amount of power we should time it with the last digit of .
This is known as the recursive way to calculate the weight we need to put a digit at the front of the num in decimal.
A more elegant solution
Assume that we already know how to reverse a shorter number given that part of the number is already reversed (Suppose we divide 123456 into 1234 and 65):
We can get a shorter number by removing the last digit (1234 -> 123)
We can extend the partial solution by appending the last digit (65 -> 654)
We just return the value returned by the recursive call!
Code Implementation:
The base case means that we there is no digit remaining, we have already reversed all the digit! And the elegant idea here is we shift the reversed digit right by one "bit", that saves us from the trouble of calculating the power! Awesome!
4. Unique*
A pretty awesome question to thinking about!!!
Setup (Preparation)
First thing first, we can use a while
loop inside a for
loop to find the how many times a factor has repeated. The implementation is below:
Rememebr to define another variable curr
to store the num n
. And remember to initialize the count
to 0 every time you start with a different factor.
First Optimization
Then let's think about how to improve the efficieny, first we can check the factor tilll sqrt(n)
instead of n
.
Now, we can change our code to below
Remember the part outside the loop, see Proof (Why can we change the loop condition to sqrt(n)?).
Second Optimization
Next let's think about it deeper. Since we are dealing with curr
every time in the loop, so actually we are finding the factors of curr
instead of n
. So, we can change the condition of our loop to ...sqrt(curr)...
. Below is the further optimized version:
Third Optimization
Can we do it even better? Since now we still cannot pass the test case 5, which is when the input is . Actually, we can stop our loop is the curr == 1
and when our curr
is a prime. So, we can optimize our code further to below:
Fourth Optimization
Before we check whether the factor is a prime or not, we can check whether the factor is indeed a factor or not. If not, then we don't need to check whether it's prime or not. This will also improve the efficiency. (This is the short-circuiting we have learend in the lecture!)
Fifth Optimization
But, see how, the most interesting part now comes! We can do this even without using is_prime()
!!! Think about it – we are starting with the smallest factor, and we divide the input with the factor as many times as we can. So at the end of the for loop, we can assert that, curr
is not divisible by anything between 2 and factor
. Consequently, the next factor for curr
has to be prime! Similar to this Proof (Why can we change the loop condition to sqrt(n)?) right? So, we've freed is_prime()
and the following code works just fine!
Note that in the loop condition, we set the terminating factor to be sqrt(n)
.
Sixth Optimization
Continue thinking about it? Can we optimize further? The answer is yes!!! Using the idea of narrowing down the loop condition from n
to curr
in the Second Optimization, we can apply this idea here too.
So, now our most succinct code should be:
5. Look-N-Say
The first part if "look", which is implemented as below:
The second part is "say", which is implemented as below:
Now, combining these two parts, we can get our "main" function:
The function above perform one step of look and say. To find the -th look-n-say number, we simply do this:
% 100000000
here is to get the last 8 digits only for generating the next number.
Tips
Marks won't be deducted if you use
break/continue
statement correctly in the loop.The use of
return
statement in the loop is allowed in the loop. It will cause the current stack frame to the function to be destroyed.
Last updated