-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathFibFrog.php
165 lines (136 loc) · 4.83 KB
/
FibFrog.php
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
<?php
/*
The Fibonacci sequence is defined using the following recursive formula:
F(0) = 0
F(1) = 1
F(M) = F(M - 1) + F(M - 2) if M >= 2
A small frog wants to get to the other side of a river.
The frog is initially located at one bank of the river (position −1)
and wants to get to the other bank (position N).
The frog can jump over any distance F(K), where F(K) is the K-th Fibonacci number.
Luckily, there are many leaves on the river, and the frog can jump between the leaves,
but only in the direction of the bank at position N.
The leaves on the river are represented in a zero-indexed array A consisting of N integers.
Consecutive elements of array A represent consecutive positions from 0 to N − 1 on the river.
Array A contains only 0s and/or 1s:
0 represents a position without a leaf;
1 represents a position containing a leaf.
The goal is to count the minimum number of jumps in which the frog
can get to the other side of the river (from position −1 to position N).
The frog can jump between positions −1 and N (the banks of the river)
and every position containing a leaf.
For example, consider array A such that:
A[0] = 0
A[1] = 0
A[2] = 0
A[3] = 1
A[4] = 1
A[5] = 0
A[6] = 1
A[7] = 0
A[8] = 0
A[9] = 0
A[10] = 0
The frog can make three jumps of length F(5) = 5, F(3) = 2 and F(5) = 5.
Write a function:
function solution($A);
that, given a zero-indexed array A consisting of N integers,
returns the minimum number of jumps by which the frog can get to the other side of the river.
If the frog cannot reach the other side of the river, the function should return −1.
For example, given:
A[0] = 0
A[1] = 0
A[2] = 0
A[3] = 1
A[4] = 1
A[5] = 0
A[6] = 1
A[7] = 0
A[8] = 0
A[9] = 0
A[10] = 0
the function should return 3, as explained above.
Assume that:
N is an integer within the range [0..100,000];
each element of array A is an integer that can have one of the following values: 0, 1.
Complexity:
expected worst-case time complexity is O(N*log(N));
expected worst-case space complexity is O(N),
beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
*/
/*
* CODILITY ANALYSIS: https://codility.com/demo/results/demo2NGVWM-CS4/
* LEVEL: HARD
* Correctness: 100%
* Performance: 100%
* Task score: 100%
*/
function solution($A)
{
// $A represents consecutive positions from 0 to N − 1,
// we will add last N position, which represents the other bank of the river
array_push($A, 1);
// number of positions
$N = count($A);
// valid frog jump Fibonacci distances, in range from 1 to full river width,
// key represents Fibonacci number/distance, and value is K-th number,
// array is reversed for later condition speed
$validFibonacciDistances = array_flip(getValidFibonacciDistances($N));
// minimum number of jumps for frog to get to the other bank of the river
$minJumps = null;
// minimum number of jumps to reach some Fibonacci distance
$jumps = array();
// at start, frog is at position -1 with 0 jumps
$jumps[-1] = 0;
// iterating while all jump combinations are not iterated, and while minimum number of jumps is not found
while($jumps && is_null($minJumps))
{
$currentPosition = key($jumps);
$jumpCount = current($jumps);
// seeking for next possible positions using Breadth First Search algorithm
foreach($validFibonacciDistances as $fibonacciJump => $forFibonnaciNumber)
{
$nextPosition = $currentPosition + $fibonacciJump;
// if position is not bigger than other bank of the river position,
// has a leaf, and represents Fibonacci distance,
if(($nextPosition <= $N - 1) && $A[$nextPosition] === 1 && !isset($jumps[$nextPosition]))
{
$jumps[$nextPosition] = $jumpCount + 1;
// if position represents other bank of the river
if($nextPosition === $N - 1)
$minJumps = $jumps[$nextPosition];
}
}
// current position is processed
unset($jumps[$currentPosition]);
}
return !empty($minJumps) ? $minJumps : -1;
}
/**
* Calculates valid Fibonacci frog jump distances. Fibonacci sequence is calculated dynamically.
*
* @param int $riverWidth Represent river width
* @return array $fibJumps Fibonacci jumps distances
*/
function getValidFibonacciDistances($riverWidth)
{
$fibJumps = array();
$fibJumps[0] = 0;
$fibJumps[1] = 1;
$i = 2;
$fibonacci = 0;
// while last Fibonacci number is smaller than the distance
while($fibonacci <= $riverWidth)
{
$fibonacci = $fibJumps[$i-1] + $fibJumps[$i-2];
if($fibonacci <= $riverWidth)
$fibJumps[$i] = $fibonacci;
$i++;
}
// F(0) = 0 => this is not a valid jump so we omit F(0)
unset($fibJumps[0]);
// F(1) = F(2) = 1 // this distance is duplicated, so we omit F(1)
unset($fibJumps[1]);
return $fibJumps;
}