Standardized testing usually comes with a scan-tron or some type of answer document that records your answer. A computer or human(s) would then check your answers and determine your grade. So here, given a scan-tron and the answer key, determine the score and questions missed if any. A scan-tron is just a document with multiple lines with answers in which the user fills in (in this case, circled). Example:

1. |a| b c d

As you can see, this is question 1 with answer choice a selected since it has a box around it. For the challenge, you will be given a scan-tron with n questions ( 1 <= n <= 10) with only four answers denoted as a, b, c, or d. The answer key will be given as a string with no spaces and with all lowercase. Example scan-tron with answer key:

1. |a| b c d
2. a |b| c d
3. a b |c| d

Answer Key

You can take in the answer key and scan-tron as separate inputs or in a chosen order as long they can be identified (i.e the answer key is separated from the scan-tron). Scores will be rounded to the nearest tenth of a point. Example output for the above:

Score: 66.7
Missed #: 3

Other acceptable answer would be:


or if multiple questions are missed

3 4 5

as long the question numbers for those missed are separated from the by spaces and not on the same line as the score.

Rules and Specs

  • The scan-tron can be inputted as a multi-line string or one question at a time (as a string with newlines is acceptable)
  • Given a scan-tron and answer key, you must output the score on one line and the question(s) missed on another, with the numbers separated by spaces. If no questions are missed, no question numbers should be outputted
  • Scores are rounded to the nearest tenth
  • Selected answers are surrounded by this box:

    | |
  • On the scan-tron, every question takes three spaces (the top and bottom of the box takes two extra lines)
  • Must work for the above example
  • Assume that there will always be only one answer boxed

Winning Criteria

Shortest code wins!

  • \$\begingroup\$ the scan-tron can be a list of questions ? And each question be a single string with newlines? \$\endgroup\$
    – Rod
    Mar 29, 2017 at 21:30
  • \$\begingroup\$ @Rod Yes and I will clarify that \$\endgroup\$ Mar 29, 2017 at 21:34
  • 2
    \$\begingroup\$ The language of "missed" is confusing to me, since a "missed" question could mean a question that the student failed to answer (as opposed to your apparent meaning, answered incorrectly). \$\endgroup\$
    – DLosc
    Mar 29, 2017 at 22:04
  • \$\begingroup\$ @DLosc There will always be only one circled answer \$\endgroup\$ Mar 29, 2017 at 22:13
  • \$\begingroup\$ Is a score like 50 acceptable, or does it have to be 50.0? \$\endgroup\$
    – DLosc
    Mar 29, 2017 at 22:22

8 Answers 8


Stacked, 68 + 1 = 69 bytes

'|'split[#'1-]NO neq::size:@z~>*[]YES' '#`out is0 sum z/100*1 nround

Try it online! +1 for -p flag (this script can be executed as stacked -pe "...")

Takes two inputs from the top of the stack.

Some interesting features:

[    ]NO   do not keep members where
 #'          its length
   1-          -1
             is truthy (in this case, not equal to zero).

This yields all letters surrounded by pipes.

:                 duplicate indices of incorrect answers
 size             length of incorrect answers
     :@z          (stored into z)
        ~>        range from 1 to this length
          *       and multiply by this range
           []YES  keep truthy elements

This gives us all incorrect question numbers.


Python 2, 94 93 bytes

-1 byte thanks to L3viathan

w=[i+1for i in range(l)if"|%s|"%a[i]not in s[i]]

Try it online!

  • \$\begingroup\$ Nice, much better than mine. You can replace 100. with 1e2 \$\endgroup\$
    – L3viathan
    Mar 29, 2017 at 22:09
  • \$\begingroup\$ I don't believe this meets the requirement to round the score to "the nearest tenth of a point," does it? \$\endgroup\$
    – DLosc
    Mar 30, 2017 at 2:11

Pip, 49 46 44 48 45 bytes

Ugh, that rounding takes so many bytes... 44 bytes of code, +1 for -s flag.


Takes input as command-line arguments (the scan-tron page will need quoting and escaping of newlines if you run it from an actual command line). Outputs the missed questions first, then the score. Try it online!


I'm gonna do this in two parts: the incorrect questions list and the score.

                            a,b are cmdline args, u is nil, n is newline (implicit)
                            Note that a string like n, in math contexts, is equivalent to 0
                 a@`\|..`   Find all occurrences in a of | followed by 2 chars
                            Because regex matches don't overlap, this does what we need
    {         }MZ        b  Zip with b and map this function to each pair of items:
     ++n                     Increment n (so the first time through, it's 1)
        bNa                  Is 2nd arg a substring of 1st?
           ?un               If so, return nil; if not, return n
                            Now we have a list containing nil for correct questions
                            and the question number for incorrect questions
 _FI                        Filter on identity function (keep only truthy values)
P                           Print, joining on spaces (-s flag)

                       a,b are cmdline args, m is 1000 (implicit)
            ...        The code from the first part
           #           Length of that list (i.e. number of incorrect questions)
      m/#b*            Times 1000/(number of questions)
    m-                 Subtracted from 1000
 /2+                   Plus 1/2 (= 0.5)
                       We now have a number like 667.1666666666667
(              )//1    Int-divide by 1 to truncate
                   /t  and divide that by 10
                       Print (implicit)

05AB1E, 43 bytes


Try it online!


U                                            # store the answer key in X
 |3ô                                         # split the question-rows in chunks of 3
    ø`                                       # zip and flatten
      \                                      # discard top of stack, leaving the list of
                                             # answer rows on top
       v                                     # for each answer row
         y'|k                                # get the index of the first "|"
        y    >è                              # get the character after that from the row
               XNèQ                          # compare it to the corresponding entry in 
                                             # the answer key
                   ˆ                         # add it to the global list
                    }                        # end loop
                     ¯O                      # calculate the number of correct answers
                       Xg/                   # divide by the length of the answer key
                          3°*                # multiply by 1000
                             2z+             # add 0.5
                                ï            # convert to integer
                                 T/          # divide by 10
                                   XgL       # push range [1 ... len(answer key)]
                                      ¯_Ï    # keep only numbers corresponding to 
                                             # wrong answers
                                          ‚» # format output

Batch, 242 bytes

@echo off
set m=
set "l=%l:*|=%
if %l:~,1%==%k:~,1% (set/as+=1)else set m=%m% %c%
set k=%k:~1%
if not "%k%"=="" goto l

Reads in the answer key on STDIN first, then n*3 question rows. Note: Score is printed without a leading zero if it is less than 1.0. Missed answers are printed with a leading space.


JavaScript (ES6), 88 bytes

x=>y=>x.replace(/\w(?=\|)/g,c=>c==y[i++]?t++:a+=i+" ",a=i=t="")&&(t/i*1e3+.5|0)/10+`

I could save 5 bytes by using commas and returning everything one one line:


CJam, 47 45 bytes


Try it online!


The program is in three main parts:

Right/wrong list

l                    e# Read the first line of input (answer key)
 qN/                 e# Read the rest of the input and split it on newlines
    (;3%             e# Delete the first line, then select every 3rd line 
        _            e# Duplicate the array
         '|f#        e# Find the index of the first | in each answer
             :)      e# Increment each, gives the index of the selected letter for each answer
               .=    e# Vectorized get-element-at with the answer strings
                 .=  e# Vectorized equality check with the answer key

After this section, we have an array of 0s and 1s, where 0 indicates a wrong answer and 1 a right answer.


__              e# Duplicate the right/wrong list twice
  :+            e# Take the sum of it (number of right answers)
    \,          e# Swap top elements and take the length (total number of questions)
      d/        e# Divide (casting to double so it's not integer division)
        e2      e# Multiply by 10^2
          XmO   e# Round to 1 decimal place
             n  e# Pop and print with a newline

After this section, the stack contains only the right/wrong list, and the percentage score has been output.

Wrong answers

:!            e# Logically negate each element of the right/wrong list
  _,,:)       e# Generate the inclusive range 1...length(list)
       .*     e# Vectorized multiplication of the two lists
         0-   e# Remove any 0s from the result
           p  e# Print it

Jolf, 46 bytes

I can't seem to break 46 bytes. I have two solutions of this length. Try one here!

ΆRγψ~mΖ mi«\|..»d?=€H.xSEhSdHήSmX*~1/-lζlγlζ_1

(Replace with 0x7f in the next one)


In either case, 15 bytes for rounding: mX*~1/-lζlγlζ_1. They are, for the most part, the same, except one uses a regex match to get the results, and the other splits on pipes.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.