It is necessary to organize the registration of clients in the solarium - swift

I have a task that I have not been able to solve for several weeks.
It is necessary to arrange the registration of clients in the solarium, which has S free booths. This means that there cannot be more than S people in the solarium at the same time. The duration of the stay is the same for everyone and is equal to T. At the input, we get an array with the recording time for each new client.
For example:
1, 3, 5, 1, 8, 5, 0, 6
S = 2
T = 3
This means that the first client wants to come from 1 to 4, the second from 3 to 6, etc. For each of them we have to output YES or NO, depending on whether there are free seats. For the example above, we will output YES YES YES NO YES NO YES YES.
Drawing for the first example
Another example:
1, 9, 0, 7, 2, 7, 6, 4, 10, 5
S = 3
T = 4
YES YES YES YES YES YES NO YES NO NO
N, S, T (1 ≤ N, S ≤ 200 000, 1 ≤ T ≤ 1 000 000).
Maximum array length = 1 000 000
Here is an example of my solution in Swift.
I run through all the time intervals, starting from the second one, and for each one I check the number of intersections with the rest. If there are 2 intersections, I output YES, otherwise NO.
But this solution does not work correctly on the last segments, since they, among other things, also intersect with each other.
let numberOfRequest = 8
let maxPeople = 2
let maxTime = 3
var kab = 0
let timeOfRequests = [1, 3, 5, 1, 8, 5, 0, 6]
var result = [(Int, Int)]()
for i in timeOfRequests {
result.append((i, i + maxTime))
}
print("Yes")
for i in 1..<result.count {
kab = 0
for j in 0..<i {
if max(result[i].0, result[j].0) < min(result[i].1, result[j].1) {
kab += 1
}
}
if kab < 2 {
print("Yes")
} else {
print("No")
result[i] = (0, 0)
}
}
Output: Yes Yes Yes No Yes No Yes No

Related

Best way to find the largest amount of consecutive integers in a sorted array in swift, preferably not using a for loop

Given an array of integers for example let array = [1, 3, 4, 7, 8, 9, 12, 14, 15]
What is the best way of finding the largest amount of consecutive integers preferably without using a for-in loop. If we would pass this array into a function it would return 3 as '7, 8, 9' is the largest amount of consecutive integers.
let array = [1, 3, 4, 7, 8, 9, 12, 14, 15]
func getMaxConsecutives(from array: [Int]) -> Int {
var maxCount = 1
var tempMaxCount = 1
var currentNumber = array[0]
for number in array {
if currentNumber == number - 1 {
tempMaxCount += 1
maxCount = tempMaxCount > maxCount ? tempMaxCount : maxCount
currentNumber = number
} else {
tempMaxCount = 1
currentNumber = number
}
}
return maxCount
}
getMaxConsecutives(from: array)
This works as intended but I would like a more efficient solution something that is not O(n).
I appreciate any creative answers.
You can do it like this:
let array = [1, 3, 4, 7, 8, 9, 12, 14, 15]
if let maxCount = IndexSet(array).rangeView.max(by: {$0.count < $1.count})?.count {
print("The largest amount of consecutive integers: \(maxCount)")
//prints 3
}
I think I can write it more tightly (basically as a one-liner):
let array = [1, 3, 4, 7, 8, 9, 12, 14, 15]
let (_,_,result) = array.reduce((-1000,1,0)) {
$1 == $0.0+1 ? ($1,$0.1+1,max($0.2,$0.1+1)) : ($1,1,$0.2)
}
print(result) // 3
But we are still looping through the entire array — so that we are O(n) — and there is no way to avoid that. After all, think about what your eye does as it scans the array looking for the answer: it scans the whole array.
(One way to achieve some savings: You could short-circuit the loop when we are not in the middle of a run and the maximum run so far is longer than what remains of the array! But the gain might not be significant.)

For the series 1, 1, 2, 2, 4, 2, 6, what are the next terms in the sequence? What is the nth term?

i want to know the pattern for the above series in order to write the code for above series.
I am thinking that the above series is mix of two different series 1,2,4,6,...and 1,2,2,..
Please help me with this sequence and also tell whether i am thinking in correct way or not.
logic :--
series 1-> Prime-1 i.e. [1, 2, 4, 6, 10, 12, 16, 18, 22, 28, 30, 36.....]
series 2-> Number Series i.e. [1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5.....]
final output -> Alternate Series i.e. [1 1 2 2 4 2 6 3 10 3 12 3 16 4 18 4 22 4 28 4....]
Note : There might be another logic but by the given Question, this series can be identified by below program..
Please do not use for any competition Test/Exam
import math
global li_prime;global li_series;xp=0
def prime(size):
global li_prime;count = 2;
while len(li_prime)
isprime = True
for x in range(2, int(math.sqrt(count) + 1)):
if count % x == 0:
isprime = False
break
if isprime:
li_prime.append(count-1)
count += 1
def series(size):
global li_series
for i in range(size+1):
for j in range(i):
li_series.append(i)
if len(li_series)>size:
break
def main():
global xp
global li_prime
global li_series
testcase=int(input(''))
for I in range(testcase):
li_series=[]
li_prime=[]
size=int(input(''))
prime(size)
series(size)
li_prime=li_prime[:size]
li_series=li_series[:size]
lc=[]
for i in range(size//2+1):
lc.append(str(li_prime[i]))
lc.append(str(li_series[i]))
lc=lc[:size]
main()
It is series whose greatest common divisior (gcd) is 1 also known as Euler's Totient Function.
series format = {1 1 2 2 4 2 6 32 ..... 168 80 216 120 164 100}
Code:
public static void main(String[] args) {
//n is the input for the size of the series
for(int j=1;j<=n;j++){
System.out.print(calSeriesVal(j)+" ");
}
}
private static int calDivisor(int a, int b)
{
if (a == 0)
return b;
return calDivisor(b % a, a);
}
private static int calSeriesVal(int n)
{
int val = 1;
for (int i = 2; i < n; i++)
if (calDivisor(i, n) == 1)
val++;
return val;
}

does Swift array.count get evaluated each time in a loop

I suppose this is a question that must get asked for every language, but when you write for example:
while i < array.count {
...
}
does array.count get evaluated each time the loop runs? Is it better to store it in a let constant before running the loop like this?
let length = array.count
while i < length {
...
}
Array gets the count property because it conforms to Collection. The documentation for count in Collection states
Complexity: O(1) if the collection conforms to RandomAccessCollection; otherwise, O(n), where n is the length of the collection.
Source
Since Array also conforms to RandomAccessCollection, it is a constant time operation to get the count of the array. There shouldn't be any major performance difference between getting it once at the start vs every loop iteration.
while loops (and do while loops) have their predicates evaluated on each iteration.
for loops evaluate the sequences once.
Here's is a demonstration:
var array: [Int]
print("Test Case 1 - while i < array.count")
array = [1, 2, 3, 4, 5, 6]
var i = 0
while i < array.count {
print(array[i])
if i < 3 { array.append(123) }
i += 1
}
print("\r\nTest Case 2 - for i in array.indices")
array = [1, 2, 3, 4, 5, 6]
for i in array.indices {
print(array[i])
if i < 3 { array.append(123) }
}
print("\r\nTest Case 3 - for i in 0 ..< array.count")
array = [1, 2, 3, 4, 5, 6]
for i in 0 ..< array.count {
print(array[i])
if i < 3 { array.append(123) }
}
Test Case 1 - while i < array.count
1
2
3
4
5
6
123
123
123
Test Case 2 - for i in array.indices
1
2
3
4
5
6
Test Case 3 - for i in 0 ..< array.count
1
2
3
4
5
6
Yes it's evaluated on each iteration.
Assigning to a constant will be slightly more performant. However with all of the optimisations in a modern compiler I wouldn't bother. Unless the loop count is going to be humongous.
Careful with for loops like the following. Since elems.count is part of a range that gets constructed once at the top of the loop, it is evaluated exactly once. The following code will die when i = 4:
var elems = [1, 2, 3, 4, 5, 6]
for i in 0 ..< elems.count {
if i % 2 == 0 { // remove even elements
elems.remove(at: i)
}
}
The array.count in your while does indeed get evaluated each time the condition is evaluated.
Yes, it gets called every time
Let's run a simple test, first of all we need the following Array Extension
extension Array {
var myCustomCount: Int {
print("myCustomCount")
return self.count
}
}
And then we can try this code
let nums = [1, 2, 3, 4, 5]
var i = 0
while i < nums.myCustomCount {
i += 1
}
The output is
myCustomCount
myCustomCount
myCustomCount
myCustomCount
myCustomCount
myCustomCount

Check a multiple in Swift?

I am trying to find the odd numbers and a multiple of 7 between a 1 to 100 and append them into an array. I have got this far:
var results: [Int] = []
for n in 1...100 {
if n / 2 != 0 && 7 / 100 == 0 {
results.append(n)
}
}
Your conditions are incorrect. You want to use "modular arithmetic"
Odd numbers are not divisible by 2. To check this use:
if n % 2 != 0
The % is the mod function and it returns the remainder of the division (e.g. 5 / 2 is 2.5 but integers don't have decimals, so the integer result is 2 with a remainder of 1 and 5 / 2 => 2 and 5 % 2 => 1)
To check if it's divisible by 7, use the same principle:
if n % 7 == 0
The remainder is 0 if the dividend is divisible by the divisor. The complete if condition is:
if n % 2 != 0 && n % 7 == 0
You can also use n % 2 == 1 because the remainder is always 1. The result of any mod function, a % b, is always between 0 and b - 1.
Or, using the new function isMultiple(of:, that final condition would be:
if !n.isMultiple(of: 2) && n.isMultiple(of: 7)
Swift 5:
Since Swift 5 has been released, you could use isMultiple(of:) method.
In your case, you should check if it is not multiple of ... :
if !n.isMultiple(of: 2)
Swift 5 is coming with isMultiple(of:) method for integers , so you can try
let res = Array(1...100).filter { !$0.isMultiple(of:2) && $0.isMultiple(of:7) }
Here is an efficient and concise way of getting the odd multiples of 7 less than or equal to 100 :
let results: [Int] = Array(stride(from: 7, through: 100, by: 14))
You can also use the built-in filter to do an operation on only qualified members of an array. Here is how that'd go in your case for example
var result = Array(1...100).filter { (number) -> Bool in
return (number % 2 != 0 && number % 7 == 0)
}
print(result) // will print [7, 21, 35, 49, 63, 77, 91]
You can read more about filter in the doc but here is the basics: it goes through each element and collects elements that return true on the condition. So it filters the array and returns what you want

How to check if a number can be represented as a sum of some given numbers

I've got a list of some integers, e.g. [1, 2, 3, 4, 5, 10]
And I've another integer (N). For example, N = 19.
I want to check if my integer can be represented as a sum of any amount of numbers in my list:
19 = 10 + 5 + 4
or
19 = 10 + 4 + 3 + 2
Every number from the list can be used only once. N can raise up to 2 thousand or more. Size of the list can reach 200 integers.
Is there a good way to solve this problem?
4 years and a half later, this question is answered by Jonathan.
I want to post two implementations (bruteforce and Jonathan's) in Python and their performance comparison.
def check_sum_bruteforce(numbers, n):
# This bruteforce approach can be improved (for some cases) by
# returning True as soon as the needed sum is found;
sums = []
for number in numbers:
for sum_ in sums[:]:
sums.append(sum_ + number)
sums.append(number)
return n in sums
def check_sum_optimized(numbers, n):
sums1, sums2 = [], []
numbers1 = numbers[:len(numbers) // 2]
numbers2 = numbers[len(numbers) // 2:]
for sums, numbers_ in ((sums1, numbers1), (sums2, numbers2)):
for number in numbers_:
for sum_ in sums[:]:
sums.append(sum_ + number)
sums.append(number)
for sum_ in sums1:
if n - sum_ in sums2:
return True
return False
assert check_sum_bruteforce([1, 2, 3, 4, 5, 10], 19)
assert check_sum_optimized([1, 2, 3, 4, 5, 10], 19)
import timeit
print(
"Bruteforce approach (10000 times):",
timeit.timeit(
'check_sum_bruteforce([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 200)',
number=10000,
globals=globals()
)
)
print(
"Optimized approach by Jonathan (10000 times):",
timeit.timeit(
'check_sum_optimized([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 200)',
number=10000,
globals=globals()
)
)
Output (the float numbers are seconds):
Bruteforce approach (10000 times): 1.830944365834205
Optimized approach by Jonathan (10000 times): 0.34162875449254027
The brute force approach requires generating 2^(array_size)-1 subsets to be summed and compared against target N.
The run time can be dramatically improved by simply splitting the problem in two. Store, in sets, all of the possible sums for one half of the array and the other half separately. It can now be determined by checking for every number n in one set if the complementN-n exists in the other set.
This optimization brings the complexity down to approximately: 2^(array_size/2)-1+2^(array_size/2)-1=2^(array_size/2 + 1)-2
Half of the original.
Here is a c++ implementation using this idea.
#include <bits/stdc++.h>
using namespace std;
bool sum_search(vector<int> myarray, int N) {
//values for splitting the array in two
int right=myarray.size()-1,middle=(myarray.size()-1)/2;
set<int> all_possible_sums1,all_possible_sums2;
//iterate over the first half of the array
for(int i=0;i<middle;i++) {
//buffer set that will hold new possible sums
set<int> buffer_set;
//every value currently in the set is used to make new possible sums
for(set<int>::iterator set_iterator=all_possible_sums1.begin();set_iterator!=all_possible_sums1.end();set_iterator++)
buffer_set.insert(myarray[i]+*set_iterator);
all_possible_sums1.insert(myarray[i]);
//transfer buffer into the main set
for(set<int>::iterator set_iterator=buffer_set.begin();set_iterator!=buffer_set.end();set_iterator++)
all_possible_sums1.insert(*set_iterator);
}
//iterator over the second half of the array
for(int i=middle;i<right+1;i++) {
set<int> buffer_set;
for(set<int>::iterator set_iterator=all_possible_sums2.begin();set_iterator!=all_possible_sums2.end();set_iterator++)
buffer_set.insert(myarray[i]+*set_iterator);
all_possible_sums2.insert(myarray[i]);
for(set<int>::iterator set_iterator=buffer_set.begin();set_iterator!=buffer_set.end();set_iterator++)
all_possible_sums2.insert(*set_iterator);
}
//for every element in the first set, check if the the second set has the complemenent to make N
for(set<int>::iterator set_iterator=all_possible_sums1.begin();set_iterator!=all_possible_sums1.end();set_iterator++)
if(all_possible_sums2.find(N-*set_iterator)!=all_possible_sums2.end())
return true;
return false;
}
Ugly and brute force approach:
a = [1, 2, 3, 4, 5, 10]
b = []
a.size.times do |c|
b << a.combination(c).select{|d| d.reduce(&:+) == 19 }
end
puts b.flatten(1).inspect