Ambiguous Countdown with Broken Display Segments
National Olympiad — National round (2014 season)
Submission name: svetofar.cpp
Problem summary
A two-digit seven-segment countdown displays 00…99, but some lamps are broken. Given broken and lit lamp labels, count compatible true values.
Input
Broken count and labels, then lit count and labels.
Output
Number of possible countdown values.
Constraints
Fourteen labels; within each digit labels 1…7 are top, upper-left, upper-right, middle, lower-left, lower-right, bottom. Add 7 for the right digit.
Worked example
Input and output for the worked example discussed below.
Input
6 1 4 6 9 11 13 6 3 5 7 8 10 14
Output
2
Solution analysis
- Encode the required segments of each digit as seven bits using the numbering in the original diagram. The tens digit occupies bits 0…6 and units bits 7…13.
- For every candidate 00…99, combine its digit masks and remove the broken lamps. The remaining mask must equal the observed lit mask exactly: unlit working lamps constrain the answer too.
- Always include a leading zero for a one-digit number. In the sample the broken segments make 23 and 29 produce exactly the observed lights, giving two possible countdown values.
Why it works
For each true value, its digit masks specify every lamp that would work. Removing broken lamps predicts exactly its visible pattern. Exhaustive equality tests therefore accept all and only compatible values.
Watch out. Match the diagram’s numbering. A subset check is insufficient: additional working lights contradict the observation. Include 00 and leading zeros.
Commented C++17 solution
An independently written complete program with standard headers.
#include<iostream>
#include<string>
using namespace std;
int main(){
const string segments[10]={
"123567","36","13457","13467","2346","12467","124567","136","1234567","123467"};
int mask[10]={};
for(int digit=0;digit<=9;digit++){
for(char lamp:segments[digit]){
mask[digit]|=1<<(lamp-'1');
}
}
int count;
int broken=0;
int lit=0;
cin>>count;
for(int i=0;i<count;i++){
int lamp;
cin>>lamp;
broken|=1<<(lamp-1);
}
cin>>count;
for(int i=0;i<count;i++){
int lamp;
cin>>lamp;
lit|=1<<(lamp-1);
}
int answer=0;
for(int value=0;value<=99;value++){
int expected=mask[value/10]|(mask[value%10]<<7);
// Failed lamps disappear; all working segments must match exactly.
if((expected&~broken)==lit){
answer++;
}
}
cout<<answer<<'\n';
}