Skip to content

Commit 522aca9

Browse files
Merge pull request #166 from abhisheks008/main
Ugly Numbers using Dynamic Programming
2 parents 1fa7ae8 + aff8b22 commit 522aca9

File tree

6 files changed

+231
-0
lines changed

6 files changed

+231
-0
lines changed
4.86 KB
Loading
4.96 KB
Loading
5.02 KB
Loading
5.15 KB
Loading
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# Ugly Numbers using Dynamic Programming
2+
Language used : **Python 3**
3+
4+
## 🎯 Aim
5+
The aim of this script is to find out the n'th ugly number using Dynamic Programming.
6+
7+
## 👉 Purpose
8+
The main purpose of this script is to show the implementation of Dynamic programming on finding out the n'th ugly number.
9+
10+
## 📄 Description
11+
Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, … shows the first 11 ugly numbers. By convention, 1 is included.
12+
**Given a number n, the task is to find n’th Ugly number.**
13+
14+
**Examples:**
15+
```
16+
Input : n = 7
17+
Output : 8
18+
19+
Input : n = 10
20+
Output : 12
21+
22+
Input : n = 15
23+
Output : 24
24+
25+
Input : n = 150
26+
Output : 5832
27+
```
28+
29+
## 📈 Workflow of the script
30+
- `getNthUglyNo` - The main function of the script to find out the Ugly number using Dynamic Approach.
31+
- `main` - This is the driver code for this code/script.
32+
33+
## 📃 Explanation
34+
Here is a time efficient solution with O(n) extra space. The ugly-number sequence is 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, …
35+
because every number can only be divided by 2, 3, 5, one way to look at the sequence is to split the sequence to three groups as below:
36+
(1) 1×2, 2×2, 3×2, 4×2, 5×2, …
37+
(2) 1×3, 2×3, 3×3, 4×3, 5×3, …
38+
(3) 1×5, 2×5, 3×5, 4×5, 5×5, …
39+
We can find that every subsequence is the ugly-sequence itself (1, 2, 3, 4, 5, …) multiply 2, 3, 5. Then we use similar merge method as merge sort, to get every ugly number from the three subsequences. Every step we choose the smallest one, and move one step after.
40+
```
41+
1. Declare an array for ugly numbers: ugly[n]
42+
2. Initialize first ugly no: ugly[0] = 1
43+
3. Initialize three array index variables i2, i3, i5 to point to
44+
1st element of the ugly array:
45+
i2 = i3 = i5 =0;
46+
4. Initialize 3 choices for the next ugly no:
47+
next_mulitple_of_2 = ugly[i2]*2;
48+
next_mulitple_of_3 = ugly[i3]*3
49+
next_mulitple_of_5 = ugly[i5]*5;
50+
5. Now go in a loop to fill all ugly numbers till 150:
51+
For (i = 1; i < 150; i++ )
52+
{
53+
/* These small steps are not optimized for good
54+
readability. Will optimize them in C program */
55+
next_ugly_no = Min(next_mulitple_of_2,
56+
next_mulitple_of_3,
57+
next_mulitple_of_5);
58+
59+
ugly[i] = next_ugly_no
60+
61+
if (next_ugly_no == next_mulitple_of_2)
62+
{
63+
i2 = i2 + 1;
64+
next_mulitple_of_2 = ugly[i2]*2;
65+
}
66+
if (next_ugly_no == next_mulitple_of_3)
67+
{
68+
i3 = i3 + 1;
69+
next_mulitple_of_3 = ugly[i3]*3;
70+
}
71+
if (next_ugly_no == next_mulitple_of_5)
72+
{
73+
i5 = i5 + 1;
74+
next_mulitple_of_5 = ugly[i5]*5;
75+
}
76+
77+
}/* end of for loop */
78+
79+
6.return next_ugly_no
80+
```
81+
82+
## 🧮 Algorithm
83+
Let us see how it works,
84+
```
85+
initialize
86+
ugly[] = | 1 |
87+
i2 = i3 = i5 = 0;
88+
89+
First iteration
90+
ugly[1] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
91+
= Min(2, 3, 5)
92+
= 2
93+
ugly[] = | 1 | 2 |
94+
i2 = 1, i3 = i5 = 0 (i2 got incremented )
95+
96+
Second iteration
97+
ugly[2] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
98+
= Min(4, 3, 5)
99+
= 3
100+
ugly[] = | 1 | 2 | 3 |
101+
i2 = 1, i3 = 1, i5 = 0 (i3 got incremented )
102+
103+
Third iteration
104+
ugly[3] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
105+
= Min(4, 6, 5)
106+
= 4
107+
ugly[] = | 1 | 2 | 3 | 4 |
108+
i2 = 2, i3 = 1, i5 = 0 (i2 got incremented )
109+
110+
Fourth iteration
111+
ugly[4] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
112+
= Min(6, 6, 5)
113+
= 5
114+
ugly[] = | 1 | 2 | 3 | 4 | 5 |
115+
i2 = 2, i3 = 1, i5 = 1 (i5 got incremented )
116+
117+
Fifth iteration
118+
ugly[4] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
119+
= Min(6, 6, 10)
120+
= 6
121+
ugly[] = | 1 | 2 | 3 | 4 | 5 | 6 |
122+
i2 = 3, i3 = 2, i5 = 1 (i2 and i3 got incremented )
123+
124+
Will continue same way till I < 150
125+
```
126+
127+
## 💻 Input and Output
128+
- **Test Case 1 :**
129+
130+
![](https://github.com/abhisheks008/PyAlgo-Tree/blob/main/Dynamic%20Programming/Ugly%20Numbers/Images/ugly1.PNG)
131+
132+
- **Test Case 2 :**
133+
134+
![](https://github.com/abhisheks008/PyAlgo-Tree/blob/main/Dynamic%20Programming/Ugly%20Numbers/Images/ugly2.PNG)
135+
136+
- **Test Case 3 :**
137+
138+
![](https://github.com/abhisheks008/PyAlgo-Tree/blob/main/Dynamic%20Programming/Ugly%20Numbers/Images/ugly3.PNG)
139+
140+
- **Test Case 4 :**
141+
142+
![](https://github.com/abhisheks008/PyAlgo-Tree/blob/main/Dynamic%20Programming/Ugly%20Numbers/Images/ugly4.PNG)
143+
144+
## ⏰ Time and Space complexity
145+
- **Time Complexity:** `O(n)`.
146+
- **Space Complexity:** `O(n)`.
147+
148+
---------------------------------------------------------------
149+
## 🖋️ Author
150+
**Code contributed by, _Abhishek Sharma_, 2021 [@abhisheks008](github.com/abhisheks008)**
151+
152+
[![forthebadge made-with-python](http://ForTheBadge.com/images/badges/made-with-python.svg)](https://www.python.org/)
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Python program to find n'th Ugly number
2+
# Method : Dynamic Programming
3+
# Abhishek Sharma. 2021
4+
5+
# Problem Statement : Ugly numbers are numbers whose
6+
# only prime factors are 2, 3 or 5.
7+
# Find out the nth Ugly number, where n is
8+
# given as the input to the program.
9+
10+
# -----------------------------------------------------------------
11+
12+
# Function to get the nth ugly number
13+
14+
def getNthUglyNo(n):
15+
16+
ugly = [0] * n # To store ugly numbers
17+
18+
# 1 is the first ugly number
19+
ugly[0] = 1
20+
21+
# i2, i3, i5 will indicate indices for
22+
# 2,3,5 respectively
23+
i2 = i3 = i5 = 0
24+
25+
# Set initial multiple value
26+
next_multiple_of_2 = 2
27+
next_multiple_of_3 = 3
28+
next_multiple_of_5 = 5
29+
30+
# Start loop to find value from
31+
# ugly[1] to ugly[n]
32+
for l in range(1, n):
33+
34+
# Shoose the min value of all
35+
# available multiples
36+
ugly[l] = min(next_multiple_of_2,
37+
next_multiple_of_3,
38+
next_multiple_of_5)
39+
40+
# Increment the value of index accordingly
41+
if ugly[l] == next_multiple_of_2:
42+
i2 += 1
43+
next_multiple_of_2 = ugly[i2] * 2
44+
45+
if ugly[l] == next_multiple_of_3:
46+
i3 += 1
47+
next_multiple_of_3 = ugly[i3] * 3
48+
49+
if ugly[l] == next_multiple_of_5:
50+
i5 += 1
51+
next_multiple_of_5 = ugly[i5] * 5
52+
53+
# Return ugly[n] value
54+
return ugly[-1]
55+
56+
# Driver Code
57+
if __name__ == '__main__':
58+
print ("- Finding out n'th Ugly Number using Dynamic Method -")
59+
print ("-----------------------------------------------------")
60+
n = int(input("Enter any number : "))
61+
print ()
62+
print ("********************************************")
63+
print ("The desired Ugly number is : ",getNthUglyNo(n))
64+
65+
66+
67+
# -----------------------------------------------------------------
68+
# Input given :
69+
# - Finding out n'th Ugly Number using Dynamic Method -
70+
# -----------------------------------------------------
71+
# Enter any number : 150
72+
73+
# -----------------------------------------------------
74+
# Output :
75+
# The desired Ugly number is : 5832
76+
77+
# -----------------------------------------------------------------
78+
79+
# Code contributed by, Abhishek Sharma, 2021

0 commit comments

Comments
 (0)