# What's my question record?

There's a confusing factor in the 'Curious' badge. The "Positive question record".

(total questions - negative questions - closed - deleted)/total questions is the formula of the question record. (negative, closed and deleted 'stack' with each other. that means if a question is negative and closed, it counts as two minus.)

Luckily, you know a list of your questions. Make a program that calculates your question record.

# The Input

You will be given an array of question datas. A question data is made of 2 datas.

• The votes (integer)
• The state (o(open), c(closed), d(deleted), b (closed and deleted) is the default, You may change the type and the characters for each states.)

# Examples

• [[-1,'o'],[1,'o']] => 0.5 (2 total, 1 minus points)
• [[-1,'d'],[2,'c']] => -0.5 (2 total, 3 minus points)
• [[-1,'b']] => -2 (1 total, 3 minus points)
• [[23,'o'],[7,'c'],[7,'c'],[-1,'o'],[-5,'b'],[-11,'d'],[-3,'d'],[-3,'b'],[-15,'b']] => -0.77778(The precision is 5 digits past decimal point, rounded half-up. fractions are acceptable) (Oh my, my question record is horrible.)
•  ('Minus points' is the sum of negative, closed and deleted.)

# Rules

• Format of input is your choice. You don't necessarily need to use the format in the Examples.

Reference

• You should definitely care about that badge! Not for the sake of the badge, but because it means you're contributing with valuable content :) Mar 8, 2017 at 8:51
• You say it's part of the input format: Can I take open questions as 0, closed questions and deleted questions as -1 and closed and deleted questions as -2? Where is the limit? Mar 8, 2017 at 9:18
• @StewieGriffin I was just in the middle of writing a script using that trick! Mar 8, 2017 at 9:20
• What precision is needed for decimal output? Is fractional output acceptable?
– user45941
Mar 8, 2017 at 9:55
• As it is, nothing prevents me from posting a 0 byte answer and putting all my code in the input format. That's sort of what the dc answer does. Mar 8, 2017 at 16:04

# dc, 8 bytes

I've been waiting to use dc's feature, that the input is both data and code, for quite some time.

0d?n47Pp


The idea behind the script is that all of the number crunching will be done by the question's state representation, a valid input string. The main script's task is then to initialize the counters, read the input (and execute it as code at the same time), and print the result when done, as a fraction.

Here are the strings I use to represent the state. The OP allows non-char types!

• 'o' -> "1r[1-]sX0>X0-+r1+r"
• 'c' -> "1r[1-]sX0>X1-+r1+r"
• 'd' -> "1r[1-]sX0>X1-+r1+rrr"

The extra "rr" part at the end changes nothing, it is there to differentiate the d state from c.

• 'b' -> "1r[1-]sX0>X2-+r1+r"

Try it online! The default input there is the last example.

Test run: from the 2nd example. Negative numbers in dc are given with _ as the minus sign. This is allowed by this meta consensus.

dc -f question_record.dc <<< "_1 1r[1-]sX0>X1-+r1+rrr 2 1r[1-]sX0>X1-+r1+r"
-1/2


Explanation of the script:

0d
# push 0 twice. The bottom cell will keep track of the number of questions, and the
#top cell of the sum part of the score.
?
# read input, which in this case is actually pairs of (data, code), that do all the
#number crunching
n47Pp
# print the 2 cells as a fraction: print top, print '/' (ASCII 47), print bottom


Explanation of the state's representation: I take the c state as example code

The stack at the start of this snippet is composed of the two bottom counters, plus the integer data (the votes) that was pushed on top before this. The snippet contains both the integer value of the state (minus points) and the dc code needed to apply it.

1r[1-]sX0>X1-+r1+r


I work with the following iterative algorithm (pseudo-code) to calculate the "positive question record":

result = 0
# main script: 0
sum = 0
# main script: d
for each input question; do
# main script:?
sum += 1
# snippet: 1
sum -= v (0 if total votes are positive, 1 if negative)
# snippet: r[1-]sX0>X
sum -= minus_points (based on state)
# snippet: 1-, or 0-, or 2-
result++
# snippet: r1+
done
result = sum / result
# main script:n47Pp

• Dear downvoter, I don't mind your vote, but I would prefer an explanation if possible on why is the answer not valid or useful. I'm not the only one that represents the state differently than a char. Some use integers, other use a list/string. What I did is use a language feature that treats the input string and the input integer data the same, as code that is. Mar 8, 2017 at 12:58

# Jelly, 7 bytes

F<0S÷LC


Try it online!

Each entry in the input is a list of the vote count (an integer) and the status (a list). The status is a list of two integers, effectively a negated bit-flag:

open:             [ 0, 0]
closed:           [-1, 0]
deleted:          [ 0,-1]
closed & deleted: [-1,-1]


The tally of (negativeQuestions + closed + deleted) is then just the number of negative numbers and the final formula is then rearranged as 1-((negativeQuestions + closed + deleted)/totalQuestions):

F<0S÷LC - Main link: list as described above, d
F       - flatten d into a single list
<0     - less than 0 (vectorises)
S    - sum
L  - length of d
÷   - divide
C - complement (1 minus that)


# 05AB1E, 9 bytes

˜0‹O¹g/(>


Try it online!

Uses Jonathan Allan's algorithm, so the inputs for the state are as follows:

open:             [ 0, 0]
closed:           [-1, 0]
deleted:          [ 0,-1]
closed & deleted: [-1,-1]
Explanation:

˜0‹O¹g/(> "The program."\
˜         "Deep-flatten the list."\
0‹O      "Check how many numbers are negative."\
¹g    "Push the original list's length."\
/   "Float-divide top two stack items."\
(> "Push the complement of ToS."\

# Haskell, 70 57 bytes

13 bytes saved thanks to @Laikoni!

f=fromIntegral.length
v#s=(f v-(f.filter(<0))v+sum s)/f v


## Input format

2 lists of same length, the first containing the vote counts, the second containing the question statuses where open is 0, closed/deleted is -1 and closed+deleted ist -2.

record :: [Int] -> [Int] -> Float
record v s = fromIntegral (length v - (length.filter(<0)) v + sum s)
/ (fromIntegral.length) v


## Explanation

Nothing special. Number of votes minus the number of negative questions plus the sum of the statuses, using the input format.

This solution gets inflated quite a bit because Haskell requires the arguments of a real divison to both be real numbers. In this case, they are Integers instead, so we have to call fromIntegral on them.

• You could use a shorter function name than record, eg. an infix operator to save some bytes. Mar 9, 2017 at 14:32
• Defining f=fromIntegral.length should save some more bytes. Mar 9, 2017 at 14:39
• 57 bytes: Try it online! Mar 9, 2017 at 14:44
• Thanks, @Laikoni! I really forgot to shorten the name... And the new definition of f is a great idea. I edited your suggestions in. Mar 9, 2017 at 15:29

# Python 3, 35 bytes

lambda d:1-str(d).count('-')/len(d)


Unnamed function taking a list, d.

Try it online!

Each entry in d is a list of the vote count (an integer) and the status (a list). The status is a list of two integers, effectively a negated bit-flag:

open:             [ 0, 0]
closed:           [-1, 0]
deleted:          [ 0,-1]
closed & deleted: [-1,-1]


The tally of (negativeQuestions + closed + deleted) is then just the number of negative numbers, which is shortest to count by counting the hyphens in d cast to a string. The final formula is then rearranged as 1-((negativeQuestions + closed + deleted)/totalQuestions)

### Python 2, 35 bytes

lambda d:1-1.*d.count('-')/len(d)


Same approach, but uses the __repr__ shorthand ... and multiplies by 1. to cast the count to a float.

# Python 3, 42 bytes

lambda d:sum(1-s-(v<0)for v,s in d)/len(d)


Try it online!

Input: [[votes, status],[votes, status],...]

• open : 0
• closed : 1
• deleted : 1
• closed and deleted : 2

Example : [[-1,0],[1,1],[0,2]]

# Röda, 38 bytes

f a{[-#[a()|[0]for i if[i<0]]/#a*3+1]}


Try it online!

It's a function that takes one argument, an array, that has three values per each question: the vote count, close status and delete status. Statuses are either -1 (closed or deleted) or 0 (not closed or not deleted).

Explanation:

f a{[-#[a()|[0]for i if[i<0]]/#a*3+1]}
f a{                                 } /* function f with parameter a */
a()|                           /* push values in a to the stream */
for i                   /* for each value in the stream: */
if[i<0]           /*   if the value is negative: */
[0]                        /*     push 0 to the stream */
[                               ]  /* return: */
#[                    ]          /*   number of values in the stream */
-                                 /*   negated */
/#a*3     /*   divided by number of questions */
+1   /*   plus 1 */


Example:

main {
f([
23, 0, 0,
7, -1, 0,
7, -1, 0,
-1, 0, 0,
-5, -1, -1,
-11, 0, -1,
-3, 0, -1,
-3, -1, -1,
-15, -1, -1
])
}

• By the way, now you can try Röda programs online using the Try it online! interpreter hosted by Dennis. Mar 8, 2017 at 17:41
• @KritixiLithos That's really cool! Mar 8, 2017 at 17:52

# JS: 108 bytes

Note the first slice argument should be 1 if not running from a script. I figured that the scores don't need to be associated with each post since the effect stacks anyway.

Call by script:

node code.js totalQs numOpen numClosed numDeleted score1 score2 ...

The code:

[t,o,c,d,...s]=process.argv.slice(2).map(v=>parseInt(v));console.log((t-c-d-s.reduce((c,v)=>v<0?c+1:c,0))/t) 

## Explanation needed?

[a, ...b] = [1,2,3] gives a==1, b==[2,3]

process.argv.slice(2) gets all the arguments except the first (path to node and script respectively).

.map(v=>parseInt(v)) converts each element to a number. Hopefully nobody tries NaN inputs ;).

s.reduce((c,v)=>v<0?c+1:c,0) loops over s (scores) with a function taking the counter c and value v. If v (the score of any post) is <0 then we +1 our counter to get the number of negative posts.

(t-c-d-numberNegative) / t is the total, minus closed, minus deleted, minus negative, divided by total.

# Octave, 454342 37 bytes

OP has just said in a comment that it's OK to take the state of questions on this format:

Open:              0
Closed:           -1
Deleted:          -1
Closed+Deleted:   -2


That makes the challenge quite a bit simpler:

@(v,s)(rows(v)-v<0-sum(s))/rows(v)


Old answer, from when the rules were a bit more strict.

@(v,s)((r=nnz(s))-nnz([v<0,s<100,s<99]))/r


This takes two variables as input, the votes, v and the state s, both as row vectors. It counts the number of rows, subtracts the total amount of negative votes, the number of close votes and the number of delete votes, then finally divides by the number of questions again.

# Mathematica, 32 bytes

1-Count[#,a_/;a<0,∞]/Length@#&


Anonymous function. Takes a list of pairs of integers and states, where the states are translated from the problem output specification as shown below:

o: {0, 0}
c: {-1, 0}
d: {0, -1}
b: {-1, -1}


Returns a rational number as output. The Unicode character is U+221E INFINITY for \[Infinity]. The algorithm used is conceptually similar to those of other answers.

## JavaScript (ES6), 53 46 bytes

a=>a.reduce((r,[v,s])=>r-(v<0)-s,l=a.length)/l


Takes the state as 0 for a closed NOR deleted question, 1 for a closed XOR deleted question, 2 for a closed AND deleted question.

## Batch, 99 bytes

@set/ar=n=o=0,c=d=-1,b=-513
@for %%v in (%*)do @set/a"r+=%%v>>9,n+=1
@set/ar+=n/=2
@echo %r%/%n%


Takes input as a single list of votes (limited to ±500 per question) and statuses. Prints an unreduced fraction. 218 bytes to print using decimals:

@set/ar=n=o=0,c=d=-1,b=-513
@for %%v in (%*)do @set/a"r+=%%v>>9,n+=1
@set/a"n/=2,r=r*200000/n+200001,r+=r>>31,r>>=1
@if %r:-=% geq 100000 echo %r:~,-5%.%r:~-5%&exit/b
@set/a"r+=(r>>31|1)*1000000
@echo %r:~,-7%0.%r:~-5%
`