'Beautiful arrays' CodeChef, how to input data - python

Here's the problem statement:
An array a is called beautiful if for every pair of numbers ai, aj, (i
≠ j), there exists an ak such that ak = ai * aj. Note that k can be
equal to i or j too.
Find out whether the given array a is beautiful or not!
Input
First line of the input contains an integer T denoting the number of
test cases. T test cases follow.
First line of each test case contains an integer n denoting number of
elements in a.
Next line contains n space separated integers denoting the array a.
Output
For each test case, output a single line containing "yes" or "no"
(without quotes) corresponding to the answer of the problem.
Constraints
1 ≤ T ≤ 106
1 ≤ n ≤ 105
Sum of n over all the test cases ≤ 106
-109 ≤ ai ≤ 109
Example
Input
3
2
0 1
2
1 2
2
5 6
Output:
yes
yes
no
I am new to CodeChef and can't work out how to correctly take in an input, I have some code that I am trying to use to solve the beautiful arrays problem but when I run it I get a NZEC.
from collections import Counter
numCase = int(input())
for i in range(numCase):
length = input()
array = Counter(input().split(''))
answer = "no"
for i in range(length - 1):
if array[i] == 0 or array[i] == 1:
answer = "yes"
print(answer)
When I change the inputs and manually input some data the code works for me, can anybody tell me why this code doesn't work? Thanks

I think you're not checking the last element of array because of range. try this
for i in range(length)

First, your code as-is crashes when you run it by hand. Minimally you need to change length = input() to length = int(input()). The NZEC is a runtime error, which is CodeChef telling you that your code is crashing.
Second, it's best not to reference external sites. Give your potential answerers a fighting chance and give us the problem. It's not convenient to look up CodeChef, what it is, and where I can find the problem statement. Additionally, CodeChef might go away, or might be down, and then you obviously can't get an answer. That being said, I've put the problem statement in your question.
Lastly, your solution is fundamentally flawed in terms of logic (not just crashing). It does not suffice to check whether the first two items in the array are 0 and 1 respectively. You are sort of close to having an efficient solution, though. Observe the following input/output:
1
3
1 -4 -1
# Output should be "no", since -4 * -1 == 4, and 4 is not in the list.
Also, consider
1
5
0 1 2 3 4 5
# Output should be "no" since 2 * 3 == 6, but 6 is not in the list
The base case (if the array len == 1) is a "yes" output. This is not correct in my opinion (i cannot equal j, pairs are not well defined for input of length one, I could go on...). So I'm willing to give you that part of the solution since it fooled me too and it's not particularly clear.
As a side note, it seems that I've seen some misinterpretations of the problem on this thread, so I'll try to add some clarification.
An array a is called beautiful if for every pair of numbers ai, aj, (i
≠ j), there exists an ak such that ak = ai * aj. Note that k can be
equal to i or j too.
The important words here are "for every pair of numbers ai, aj there exists ak", not just some pair. This means that if we have input array [2, 3, 6], the answer is "no", because 3 * 6 == 18, but 18 is not in the array. It's tempting to think that the answer should be "yes" because 2 * 3 == 6, but that's just some pair that satisfies the relation. The question makes it clear that every pair must satisfy the relation.
Here's my solution. I was tempted not to post it, but if you really get stuck, this can be your reference. I strongly suggest you do not look at the solution right away, give yourself at least a full day to solve it, and be sure to sleep on it. You won't learn anything by copy/pasting my solution into CodeChef. Hover over the section below to see my solution.
numCase = int(input())
for i in range(numCase):
length = int(input())
array = [int(x) for x in input().split(' ')]
num_neg_ones = len([x for x in array if x == -1])
num_ones = len([x for x in array if x == 1])
num_other = len([x for x in array if x not in [0, -1, 1]])
answer = "yes"
if num_other > 1:
answer = "no"
if num_other == 1 and num_neg_ones > 0:
answer = "no"
if num_neg_ones > 1 and num_ones == 0:
answer = "no"
print(answer)

Related

Uva The 3n + 1 Problem - Wrong Answer Python

I'm trying to solve a question from onlinejudge.org - The 3n + 1 Problem using Python.
in case the link doesn't load (that happens quite frequently), below is my summarized version of the question:
Consider the following algorithm:
input n
print n
if n = 1 then STOP
if n is odd then n <- 3n + 1
else n <- n/2
GOTO 2
Given the input 22, the following sequence of numbers will be printed
22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
In the example above, the cycle length of 22 is 16.
For any two numbers i and j you are to determine the maximum cycle length over all numbers between and including both i and j.
Sample Input
1 10
100 200
201 210
900 1000
Sample Output
1 10 20
100 200 125
201 210 89
900 1000 174
And here's my code.
inputText = input().split()
inputList=[]
for index in range(0, len(inputText), 2):
inputList.append([int(inputText[index]), int(inputText[index + 1])])
def CycleLen(num):
chainList = [num]
while num > 1:
chainList.append(num//2 if num % 2 == 0 else 3*num + 1)
num = chainList[-1]
return len(chainList)
for listSet in inputList:
countList = []
minRange = min(listSet[0], listSet[1])
maxRange = max(listSet[0], listSet[1])
for num in range(minRange, maxRange + 1):
countList.append(CycleLen(num))
countList.sort()
print(listSet[0], listSet[1], countList[-1])
I'm aware of the memorization solution to make it more time efficient, but I planned to implement that only if the question rejected my answer for exceeding time limit. However, I'm straight up getting the wrong answer, and I have no idea why.
I used uDebug to see if there are any mistakes, and searched for other's solution. The most confusing part is how the online judge submits its input - single line by line, or all the lines at once. Different sources claim different things.
Please help. Thank you!
Given your code actually does generate the correct results for the given samples, it's a safe bet you're not handling the input data correctly. And, in fact, the problem statement states (my emphasis):
The input will consist of a series of pairs of integers i and j, one pair of integers per line. All integers will be less than 10,000 and greater than 0.
You should process all pairs of integers and for each pair determine the maximum cycle length over all integers between and including i and j.
Hence, your code that gets only one pair will not be sufficient. The reason it only processes one pair has to do with a misunderstanding that the code:
inputText = input().split()
will give you all the input lines, as evidenced by the loop that tries to create a list of 2-tuples from each pair:
inputList=[]
for index in range(0, len(inputText), 2):
inputList.append([int(inputText[index]), int(inputText[index + 1])])
However, input() only reads one line of input (see here for details), meaning that you will only process the first line of the multi-line input. To do it properly, you need to continuously read and process lines until the file ends.
Having said that, you may also want to reconsider the use of a lists as your first step if it exceeds the time limit. It would be far easier to just maintain the current item and a count for calculating the cycle length (for the individual cycles) and just processing input lines sequentially (for the different ranges). Neither of those aspects requires an actual list.
Addressing both those list issues (and the one-line-of-input issue mentioned above), you would end up with something like:
def CycleLen(num):
# Start with one number, the one given.
curr = num
count = 1
# Until you get to 1, increase count and calculate next.
while curr > 1:
count += 1
curr = curr // 2 if curr% 2 == 0 else curr * 3 + 1
return count
while True:
# Reads a single line and splits into integers. Any problem, exit loop.
try:
inputInt = [int(item) for item in input().split()]
if len(inputInt) != 2: break
except:
break
# Find value in the range with the longest cycle then print it.
maxCycle = 0
for number in range(min(inputInt), max(inputInt) + 1):
maxCycle = max(maxCycle, CycleLen(number))
print(inputInt[0], inputInt[1], maxCycle)

Algorithm: Factorize a integer X to get as many distinct positive integers(Y1...Yk) as possible so that (Y1+1)(Y2+1)...(Yk+1) = X

I recently met a algorithm question in open.kattis.com.
The question's link is https://open.kattis.com/problems/listgame2.
Basically, it is a question ask the players to factorize a integer X (10^3 <= X <= 10^15) to get as many distinct positive integers (Y1,...,Yk) as possible such that (Y1+1)(Y2+1)⋯(Yk+1) = X.
I already came up with a solution using Python3, which does pass several test cases but failed one of them:MyStatus
My code is:
def minFactor(n, start):
maxFactor = round(n**0.5)
for i in range(start, maxFactor+1):
if n % i == 0:
return i
return n
def distinctFactors(n):
curMaxFactor = 1
factors = []
while n > 1:
curMaxFactor = minFactor(n, curMaxFactor+1)
n //= curMaxFactor
factors.append(curMaxFactor)
# This is for the situation where the given number is the square of a prime number
# For example, when the input is 4, the returned factors would be [2,2] instead of [4]
# The if statement below are used to fix this flaw
# And since the question only requires the length of the result, deleting the last factor when repeat do works in my opinion
if factors[-1] in factors[:-1]:
del factors[-1]
return factors
num = int(input())
print(len(distinctFactors(num)))
Specifically, my idea inside the above code is quite simple. For example, when the given input is 36, I run the minFactor function to find that the minimum factor of 36 is 2 (1 is ignored in this case). Then, I get 18 by doing 36/2 and invoke minFactor(18,3) since 2 is no more distinct so I start to find the minimum factor of 18 by 3. And it is 3 clearly, so I get 6 by doing 18/3 in function distinctFactors and invoke minFactor(6,4), since 4 is smaller than sqrt(6) or 6**0.5 so 6 itself will be returned and I finally get the list factors as [2,3,6], which is correct.
I have scrutinised my code and algorithm for hours but I still cannot figure out why I failed the test case, could anyone help me with my dilemma??? Waiting for reply.
Consider the number 2**6.11**5.
Your algorithm will find 5 factors:
2
2**2
2**3
11
11**2
(11**2 this will be discarded as it is a repeat)
A 6 length answer is:
2
2**2
11
11**2
2*11
2**2*11

Bulls & cows (mastermind) in Python. Should be relatively easy

I'm new to python and I need to write a "Bulls and Cows" game (a.k.a Mastermind)
and it goes like this:
You get 2 inputs at first; 1 for the length of the secret (can be 4-6), and 2nd for the base (can be 6-10).
You can ASSUME that both the secret and the guess will have the given length (you don't need to make sure of that)
Later on, you have another 2 inputs. 1 for the secret (a chain of numbers seperated by space) and the 2nd for the base (a chain of numbers seperated by space).
if the secret has a number that equals or exceeds the base, the program will output ERROR and exit.
An example to clarify:
5 (First input, length should be 5)
8 (The base. It means that no number is allowed to be 8 or beyond. You are only allowed to use 0,1,2,3,4,5,6,7)
1 2 7 2 5 (this is the secret)
7 2 2 1 1 (this is the guess)
OUTPUT:
1 BULLS 3 COWS
Another example:
6
9
0 0 0 0 0 6
8 22 2 2 1 4
OUTPUT:
0 BULLS 0 COWS
Ok, so I started writing the code, and I wasn't sure what exactly I am supposed to be using, so I did this so far:
#get the length of the guess - an int number between 4(included) to 6(included)
secretL = input()
#get the base of the guess - an int number between 6(included) to 10(included)
secretB = input()
#get the guess
secret = raw_input()
secretsNumbers = map(int, secret.split())
#turn the chain into a singular INT number in order to make sure each of its digits does not equal or exceeds base, using %10
secretsNumbersMerge = int(''.join(map(str,secretsNumbers)))
newSecretsNumbersMerge = secretsNumbersMerge
while newSecretsNumbersMerge!= 0:
checker = newSecretsNumbersMerge%10
if checker<secretBase:
newSecretsNumbersMerge = newSecretsNumbersMerge/10
else:
print ("ERROR")
quit()
guess = raw_input()
guessNumbers = map(int, guess.split())
So far it's all good. This really makes sure the secret meets the base demands. Now I'm at the main point where I should check for bulls and cows and I'm not quite sure how to proceed from this point.
My idea is to first check for Bulls and then remove them (so it won't get mixed with cows), and then check for cows but yeah.. I'm clueless.
I'm not even sure what to use in Python.
Thanks in advance!
Here is your code but please try to understand each line of it:
import re
from collections import Counter
#get the length of the guess - an int number between 4(included) to 6(included)
secretL = input()
#get the base of the guess - an int number between 6(included) to 10(included)
secretB = input()
#get the guess
secret = raw_input()
# Check if the secret input uses a digit greater than the base value
# You can use the check on the next line as well. It can be made faster
# too by using search in place of findall.
# if len(re.findall(r"[^0-" + str(secretB) + r" ]+", secret)):
if sum((i!=" " and int(i) > secretB) for i in secret) > 0:
print("Error")
quit()
secretNumbers = map(int, secret.split())
guess = raw_input()
guessNumbers = map(int, guess.split())
# Count the bulls by iterating over the two lists simultaneously
bulls = sum(i==j for i, j in zip(secretNumbers, guessNumbers))
# Remove the bulls before counting the cows
secretNumbers, guessNumbers = zip(*((x,y) for x,y in zip(secretNumbers, guessNumbers) if x!=y))
# Cows are defined as the elements present in both the guess and the secret
# but not in the right position.
# If we ignore duplicates, this is the way to go about it.
cows = len(set(secretNumbers) & set(guessNumbers))
## If we count [1,1,2,4] and [5,3,1,1] to have 2 cows, this is how it should be:
#counter = Counter(secretNumbers) & Counter(guessNumbers)
#cows = sum(counter.itervalues())
print(str(bulls) + " BULLS " + str(cows) + " COWS")
Let me know if something is not clear and I'll add an explanation.
Also, I'm not aware of the rules of mastermind and have inferred them from your description. I'm not clear how you got 0 cows for the second example.
UPDATE 1
if sum(i > secretB for i in secretNumbers) > 0: how does it work exactly?
Please use backticks(`) to quote small pieces of code in comments, questions or answers. Now, let's break down this code into easily understandable pieces:
Consider the list comprehension [ i > secretB for i in secretNumbers]. This will generate a list of booleans. So, if your base is 6 and secretNumbers is [1,2,7,2,5], it will return [False, False, True, False, False]. (As per your comment, this is not the way the rule was to be interpreted but I'm pretty sure you can modify this condition to be what you need.)
sum() is a very useful standard built-in function in Python which returns the sum of any iterable passed to it. So, sum([1,2,3,4]) will return 10.
It remains to answer what does it mean to sum a list of boolean values. It might initially seem strange to add True to True this way, but I don't think it's unpythonic; after all, bool is a subclass of int in all versions since 2.3:
_
>>>issubclass(bool, int)
True
So, there you go: sum(i > secretB for i in secretNumbers) tells you exactly how many numbers in the input exceed the base.
UPDATE 2:
After a clarification from OP, the explanation of Update 1 doesn't apply to the code under discussion anymore though OP now understands the general technique of using list comprehensions to do powerful things.
Also, the condition for counting the COWS has been clarified and the code now lists two ways to do it - one, while ignoring duplicates; and second by counting each duplicate instance.

Is it possible to calculate the number of count inversions using quicksort?

I have already solved the problem using mergesort, now I am thinking is that possible to calculate the number using quicksort? I also coded the quicksort, but I don't know how to calculate. Here is my code:
def Merge_and_Count(AL, AR):
count=0
i = 0
j = 0
A = []
for index in range(0, len(AL) + len(AR)):
if i<len(AL) and j<len(AR):
if AL[i] > AR[j]:
A.append(AR[j])
j = j + 1
count = count+len(AL) - i
else:
A.append(AL[i])
i = i + 1
elif i<len(AL):
A.append(AL[i])
i=i+1
elif j<len(AR):
A.append(AR[j])
j=j+1
return(count,A)
def Sort_and_Count(Arrays):
if len(Arrays)==1:
return (0,Arrays)
list1=Arrays[:len(Arrays) // 2]
list2=Arrays[len(Arrays) // 2:]
(LN,list1) = Sort_and_Count(list1)
(RN,list2) = Sort_and_Count(list2)
(M,Arrays)= Merge_and_Count(list1,list2)
return (LN + RN + M,Arrays)
Generally no, because during the partitioning, when you move a value to its correct side of the pivot, you don't know how many of the values you're moving it past are smaller than it and how many are larger. So, as soon as you do that you've lost information about the number of inversions in the original input.
I come across this problem for some times, As a whole, I think it should be still ok to use quick sort to compute the inversion count, as long as we do some modification to the original quick sort algorithm. (But I have not verified it yet, sorry for that).
Consider an array 3, 6, 2, 5, 4, 1. Support we use 3 as the pivot, the most voted answer is right in that the exchange might mess the orders of the other numbers. However, we might do it different by introducing a new temporary array:
Iterates over the array for the first time. During the iteration, moves all the numbers less than 3 to the temporary array. For each such number, we also records how much number larger than 3 are before it. In this case, the number 2 has one number 6 before it, and the number 1 has 3 number 6, 5, 4 before it. This could be done by a simple counting.
Then we copy 3 into the temporary array.
Then we iterates the array again and move the numbers large than 3 into the temporary array. At last we get 2 1 3 6 5 4.
The problem is that during this process how much inversion pairs are lost? The number is the sum of all the numbers in the first step, and the count of number less than the pivot in the second step. Then we have count all the inversion numbers that one is >= pivot and another is < pivot. Then we could recursively deal with the left part and the right part.

Finding numbers from a to b not divisible by x to y

This is a problem I've been pondering for quite some time.
What is the fastest way to find all numbers from a to b that are not divisible by any number from x to y?
Consider this:
I want to find all the numbers from 1 to 10 that are not divisible by 2 to 5.
This process will become extremely slow if I where to use a linear approach;
Like this:
result = []
a = 1
b = 10
x = 2
y = 5
for i in range(a,b):
t = False
for j in range(x,y):
if i%j==0:
t = True
break
if t is False:
result.append(i)
return result
Does anybody know of any other methods of doing this with less computation time than a linear solution?
If not, can anyone see how this might be done faster, as I am blank at this point...
Sincerely,
John
[EDIT]
The range of the number are 0 to >1,e+100
This is true for a, b, x and y
You only need to check prime values in the range of the possible divisors - for example, if a value is not divisible by 2, it won't be divisible by any multiple of 2 either; likewise for every other prime and prime multiple. Thus in your example you can check 2, 3, 5 - you don't need to check 4, because anything divisible by 4 must be divisible by 2. Hence, a faster approach would be to compute primes in whatever range you are interested in, and then simply calculate which values they divide.
Another speedup is to add each value in the range you are interested in to a set: when you find that it is divisible by a number in your range, remove it from the set. You then should only be testing numbers that remain in the set - this will stop you testing numbers multiple times.
If we combine these two approaches, we see that we can create a set of all values (so in the example, a set with all values 1 to 10), and simply remove the multiples of each prime in your second range from that set.
Edit: As Patashu pointed out, this won't quite work if the prime that divides a given value is not in the set. To fix this, we can apply a similar algorithm to the above: create a set with values [a, b], for each value in the set, remove all of its multiples. So for the example given below in the comments (with [3, 6]) we'd start with 3 and remove it's multiples in the set - so 6. Hence the remaining values we need to test would be [3, 4, 5] which is what we want in this case.
Edit2: Here's a really hacked up, crappy implementation that hasn't been optimized and has horrible variable names:
def find_non_factors():
a = 1
b = 1000000
x = 200
y = 1000
z = [True for p in range(x, y+1)]
for k, i in enumerate(z):
if i:
k += x
n = 2
while n * k < y + 1:
z[(n*k) - x] = False
n += 1
k = {p for p in range(a, b+1)}
for p, v in enumerate(z):
if v:
t = p + x
n = 1
while n * t < (b + 1):
if (n * t) in k:
k.remove(n * t)
n += 1
return k
Try your original implementation with those numbers. It takes > 1 minute on my computer. This implementation takes under 2 seconds.
Ultimate optimization caveat: Do not pre-maturely optimize. Any time you attempt to optimize code, profile it to ensure it needs optimization, and profile the optimization on the same kind of data you intend it to be optimized for to confirm it is a speedup. Almost all code does not need optimization, just to give the correct answer.
If you are optimizing for small x-y and large a-b:
Create an array with length that is the lowest common multiple out of all the x, x+1, x+2... y. For example, for 2, 3, 4, 5 it would be 60, not 120.
Now populate this array with booleans - false initially for every cell, then for each number in x-y, populate all entries in the array that are multiples of that number with true.
Now for each number in a-b, index into the array modulo arraylength and if it is true, skip else if it is false, return.
You can do this a little quicker by removing from you x to y factors numbers whos prime factor expansions are strict supersets of other numbers' prime factor expansions. By which I mean - if you have 2, 3, 4, 5, 4 is 2*2 a strict superset of 2 so you can remove it and now our array length is only 30. For something like 3, 4, 5, 6 however, 4 is 2*2 and 6 is 3*2 - 6 is a superset of 3 so we remove it, but 4 is not a superset of everything so we keep it in. LCM is 3*2*2*5 = 60. Doing this kind of thing would give some speed up on its own for large a-b, and you might not need to go the array direction if that's all you need.
Also, keep in mind that if you aren't going to use the entire result of the function every single time - like, maybe sometimes you're only interested in the lowest value - write it as a generator rather than as a function. That way you can call it until you have enough numbers and then stop, saving time.

Categories

Resources