1

I am trying to solve apparatus problem described here. And I have a solution but it takes longer than 2 seconds which the time limit. I've tried to optimize my code for speed but can't get it with in the 2 second limit.

import sys
import math

for line in sys.stdin:

    line = line.strip("\n").split(" ")
    numSwitches = int(line[0])
    numPics = int(line[1])

    wiring = {}
    inValid = False
    for i in range(numPics):
        if (inValid):
            break
        x = sys.stdin.readline().strip("\n")
        f_x = sys.stdin.readline().strip("\n")

        x_ones = 0
        f_x_ones = 0

        digit = 0
        for i in range(numSwitches):
            if f_x[i]=='1':
                digit += 2**(numSwitches-i-1)
                f_x_ones += 1

        for switch in range(numSwitches):
            if (x[switch]=='1'):
                x_ones += 1
                if not (switch in wiring.keys()):
                    wiring[switch] = digit
                else:
                    wiring[switch] &= digit

        if x_ones != f_x_ones:
            inValid = True
            break

    if not inValid:
        for i in wiring.values():
            if i==0:
                inValid = True
                break

    for possibilities in set(wiring.values()):
        frequency = wiring.values().count(possibilities)
        if frequency>1:
            oneBits = 0
            while (possibilities>0):
                oneBits += (possibilities%2==1)
                possibilities /= 2
            if oneBits < frequency:
                inValid = True
                break

    if not inValid:
        print math.factorial(numSwitches-numPics)%1000003
    else:
        print 0

I'm looking for suggestions of ways I should have approached the problem or input on how I can optimize my current code.

Note: Consider the following test case:

3 2
110
011
011
011

My code finds that is invalid in the following manner. First, upon encountering the first photograph (110, 011). The wiring dictionary gets assigned the following keys and values:

wiring[0] = 011
wiring[1] = 011

This means that the first and second switch can light up either the second or third lights. Upon encountering the second photograph (011, 011). wiring is updated as follows:

wiring[1] = 011 & 011 = 011
wiring[2] = 011

Now observe that the state of wiring indicates that all three switches can light up either the second and third lights. This is an inconsistency since 3 switches have to light up three lights, here we have three switches lighting up 2 lights.

Ragnar
  • 169
  • 7
  • can we assume that when switch is on then a connected light is on as well? – Paweł Kordowski Nov 22 '15 at 00:36
  • @PawełKordowski Yes, if a switch is on, a corresponding light should be on as well. And the number of on-switches should be the same as the number of on-lights. – Ragnar Nov 22 '15 at 16:26
  • @PawełKordowski Please take a look at the edits I added to my question at the bottom. – Ragnar Nov 22 '15 at 20:59
  • go instead to the Code Review SE (I would link you but Im on ny phone), they can probably help a lot more – R Nar Nov 22 '15 at 21:12
  • This question could be suitable for [Code Review](http://codereview.stackexchange.com/help), as long as (a) your code works as intended, (b) your code is real code, rather than example code, and (c) your code is included in the body of the question. If you wish for a peer review to improve all aspects of your code, please post it on Code Review. – Phrancis Nov 22 '15 at 21:17
  • @Phrancis Thanks, I was not aware of the existence of Code Review. There are a lot of stack exchanges. – Ragnar Nov 22 '15 at 22:44
  • Can now this question be closed? https://codereview.stackexchange.com/questions/111539/programming-challenge-from-kattis-apparatus?rq=1 – hola Nov 10 '17 at 15:56

1 Answers1

0

I think this could be a solution, but I'm not sure, I can explain more tomorrow

import numpy as np
from operator import mul

def apparatus(n, m, x, y):
    if not m:
        return np.math.factorial(n) % 1000003
    result = 1
    tmp = np.matrix([False] * x.shape[1])

    for i in xrange(x.shape[1]):
        if tmp[0, i]:
            continue
        tmp0 = np.prod(x[:, i] == x, 0)
        tmp1 = np.prod(x[:, i] == y, 0)
        if np.sum(tmp1) != np.sum(tmp0):
            return 0
        result *= np.math.factorial(np.sum(tmp1))
        result %= 1000003
        tmp += tmp1

    return result

x = np.matrix([[True, True, False]])
y = np.matrix([[False, True, True]])
print apparatus(3, 1, x, y)

x = np.matrix([[True, False, False, False], [False, False, False, False]])
y = np.matrix([[True, False, False, False], [False, False, True, False]])
print apparatus(4, 2, x, y)

print apparatus(1000, 0, [], [])
Paweł Kordowski
  • 2,688
  • 1
  • 14
  • 21