-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.pony
169 lines (131 loc) · 3.73 KB
/
main.pony
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// Actor0 - The Main Actor which returns the result finally
// Actor1 - ComputeSquares for each number from 1 to N + K - 1
// Actor2 - Calculate the sum of k consequtive sqaure numbers
// Actor3 - Verifies if the number is sqaure or not
// Cores used = (user time + sys time) / real time
// /usr/bin/time ./DOSP 10000000 3 - macOS
// .\measure_time.ps1 -ProgramPath ".\DOSP.exe" -Arguments "arg1 arg2" - Windows powershell
use "collections"
use "math"
class Math
fun ceil(x: F64): USize =>
let i = x.trunc().i64()
if (x > 0) and (x > i.f64()) then
return (i + 1).usize()
else
return i.usize()
end
fun sqrt(n: USize): F64 =>
if n == 0 then return 0 end
if n == 1 then return 1 end
var left: USize = 1
var right: USize = n
while left <= right do
let mid = left + ((right - left) / 2)
let mid_squared = mid * mid
if mid_squared == n then
return mid.f64()
elseif mid_squared < n then
left = mid + 1
else
right = mid - 1
end
end
right.f64()
actor Calculator
let _env: Env
let _total: USize
let _chunk_size: USize
let _summers: Array[Summer]
new create(env: Env, n: USize, k: USize) =>
_env = env
_total = n
// _chunk_size = Math.ceil(Math.sqrt(_total)) // Adjust this based on your system and problem size
if n <= 1000 then
_chunk_size = n
else
_chunk_size = Math.ceil(Math.sqrt(n))
end
_summers = Array[Summer]
let num_summers = ((n - 1) / _chunk_size) + 1
for i in Range(0, num_summers) do
_summers.push(Summer(env, k, i * _chunk_size))
end
for i in Range(0, num_summers) do
let start = (i * _chunk_size) + 1
let endp = if ((i + 1) * _chunk_size) > n then n else (i + 1) * _chunk_size end
try
_summers(i)?.calculate_chunk(start, endp)
end
end
actor Summer
let _env: Env
let _k: USize
let _offset: USize
let _queue: Array[U64]
var _sum: U64
var _index: USize
let _checker: PerfectSquareChecker
new create(env: Env, k: USize, offset: USize) =>
_env = env
_k = k
_offset = offset
_queue = Array[U64](_k)
_sum = 0
_index = 0
_checker = PerfectSquareChecker(env)
be calculate_chunk(start: USize, endp: USize) =>
for i in Range(start, endp + 1) do
let square = (i.u64() * i.u64())
add_square(square, start)
end
fun ref add_square(square: U64, start: USize) =>
if _queue.size() == _k then
try
_sum = _sum - _queue.shift()?
end
end
_queue.push(square)
_sum = _sum + square
if _queue.size() == _k then
_checker.check_perfect_square(_sum, _offset + _index)
_index = _index + 1
end
actor PerfectSquareChecker
let _env: Env
let _results: Array[Bool]
new create(env: Env) =>
_env = env
_results = Array[Bool]
be check_perfect_square(n: U64, index: USize) =>
let result = is_perfect_square(n)
if result == true then
_env.out.print((index + 1).string())
end
_results.push(result)
fun is_perfect_square(n: U64): Bool =>
if n == 0 then return true end
if n == 1 then return true end
var left: U64 = 1
var right: U64 = n
while left <= right do
let mid = left + ((right - left) / 2)
let mid_squared = mid * mid
if mid_squared == n then
return true
elseif mid_squared < n then
left = mid + 1
else
right = mid - 1
end
end
false
actor Main
new create(env: Env) =>
try
let n = env.args(1)?.usize()?
let k = env.args(2)?.usize()?
Calculator(env, n + k, k) // to correct to start at first number of k series till n
else
env.out.print("Please provide valid numbers N and K as arguments.")
end