Help recalculate your rep!

12

A couple months ago, we had a discussion on meta about increasing the reputation awarded for upvotes on questions. Here's the basics of our current reputation system for votes:1

  • A question upvote U is worth 5 reputation.
  • An answer upvote u is worth 10 reputation.
  • A question or answer downvote d is worth -2 reputation.

There have been many different suggestions for a new system, but the current most popular is identical to the above, but with question upvotes scaled to +10 rep. This challenge is about calculating how much more rep you would earn if this system were put into place.

Let's look at an example. If the voting activity was UUUUuuuuUUUUUduuudUU, then you'd earn 121 under the current system:

U x 4 x  5 =  20 =  20
u x 4 x 10 =  40 =  60
U x 5 x  5 =  25 =  85
d x 1 x -2 =  -2 =  83
u x 3 x 10 =  30 = 113
d x 1 x -2 =  -2 = 111
U x 2 x  5 =  10 = 121
Total:             121

But the same activity would earn 176 under the new system:

U x 4 x 10 =  40 =  40
u x 4 x 10 =  40 =  80
U x 5 x 10 =  50 = 130
d x 1 x -2 =  -2 = 128
u x 3 x 10 =  30 = 158
d x 1 x -2 =  -2 = 156
U x 2 x 10 =  20 = 176
Total:             176

You would gain 55 rep from this scenario.

So far, calculating the changed rep isn't that hard; just count the number of Us and multiply by 5. Fortunately, the rep system isn't that simple: there is also a rep cap, which is the most reputation you can earn from votes in one UTC day. This is set to 200 on all sites.

Also, the rep cap applies in real time: if you have already earned 196 rep and you receive an answer upvote, you will now have 200 rep. If you get a downvote right after that, the 2 rep will be subtracted from 200, so you will have 198 rep.

With the voting activity UUUuuuuUUUUuuuuUUUUUUUd, you would earn 148 rep under the current system:

U x 3 x  5 =  15 =  15
u x 4 x 10 =  40 =  55
U x 4 x  5 =  20 =  75
u x 4 x 10 =  40 = 115
U x 7 x  5 =  35 = 150
d x 1 x -2 =  -2 = 148
Total:             148

But you would earn 198 under the new system:

U x 3 x 10 =  30 =  30
u x 4 x 10 =  40 =  70
U x 4 x 10 =  40 = 110
u x 4 x 10 =  40 = 150
U x 7 x 10 =  70 = 200 (rep capped)
d x 1 x -2 =  -2 = 198
Total:             198

Thus, the increase is 50 rep.

Challenge

Your challenge is to write a program or function that takes in a multi-line string and outputs the total rep that would be gained with the above algorithm. Each line counts as 1 UTC day, so the rep cap only applies once per line.

Test cases

(One or more lines of input, followed by the output integer.)

UUUuudd
15

UUUuUUUUuUuuUUUUudUUUUuU
57

UUUuUUUUuUuuUUUUudUUUUuU
UUUuudd
72

uuuuuuu
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
uuuuuuuuuuuuuuuuuuuu
UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
0

UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
5

(empty string)
0

UUUuuuuuUUUuuUUUUUUuuuUUUuuUUUUuuuuUUUdddddddUU
4

UUUuuuuuUUUuuUUUUUUuuuUUUuuUUUUuuuuUUUdddddddUU
UuuUUUudUU
UUUUUUUUUuuuuuuUUUUUUuuUUUUUUuuuuuUUUUUUUUuUUUuuuuUUUUuuuUUUuuuuuuUUUUUUUUuuUUUuuUU
UUu
U
d
UU
UUUUUUUUUUUU
119

This is code golf, so shortest code in bytes wins.

Related challenges: Calculate the bounded cumulative sum of a vector, Calculate your stack exchange reputation

1 This is a highly simplified version of the system. You also lose 1 rep for downvoting an answer, and there exist unupvotes, which are weird and follow rules of their own; and undownvotes, which don't even have rules to follow.

ETHproductions

Posted 2016-02-09T21:30:56.133

Reputation: 47 880

1

Nice challenge. Too bad it's not likely to happen...

– AdmBorkBork – 2016-02-09T22:00:05.370

2¹ You don't lose rep for downvoting questions; just answers. Trust me :P – Geobits – 2016-02-09T23:02:56.460

@Mego Possible, but I see the following differences: A) The full cumulative array isn't needed, just the last term. B) There is no lower bound, and the upper bound is fixed. C) The input is a string, as opposed to an array of numbers. D) Arbitrary amounts of these strings, separated by newlines, must be each run through separately and summed to get the result. – ETHproductions – 2016-02-09T23:15:22.693

1@ETHproductions All of those except B are I/O differences. The core problem is still the same. – Mego – 2016-02-09T23:40:32.150

Answers

0

Perl, 104 91 + 2 = 93 bytes

sub f{200*$.>$_[0]?$_[0]:200*$.}for(/./g){$a=/d/?-2:10;$s=f$s+$a;$o=f$o+$a-5*/U/}}{$_=$s-$o

Requires the -p flag:

$ echo UUUuUUUUuUuuUUUUudUUUUuU | perl -p recalc.pl
57
$ echo "UUUuUUUUuUuuUUUUudUUUUuU
UUUuudd" | perl -p recalc.pl
72

Breakdown:

sub f {
  # '$.' contains the line number (1, 2, ... n)
  200*$. > $_[0] ? $_[0] : 200*$.
}
for(/./g){
  $a= /d/ ? -2  : 10;
  $s=f( $s + $a );
  # /U/ returns `1` if true
  $o=f( $o + $a - 5*/U/ )
}
}{ # Eskimo exit while loop (do this after the outer (from -p) iteration)
$_=$s-$o

andlrc

Posted 2016-02-09T21:30:56.133

Reputation: 1 613

2

ES6, 104 bytes

s=>s.split`
`.map(l=>(g=U=>[...l].map(c=>(r+=eval(c))>200?r=200:0,r=0)|r,t+=g(10)-g(5)),u=10,d=-2,t=0)|t

Calculates the before and after rep for each line. My first use of eval!

Neil

Posted 2016-02-09T21:30:56.133

Reputation: 95 035

2

Haskell, 98 93 bytes

Thanks to BlackCap to golf this further. Now, I think to try lambda in later challenges, now.

x#'U'=x
_#'u'=10
_#'d'=(-2)
a&b=foldl1(\d g->min 200$d+a#g)
g=sum.map(\x->(10&x)-(5&x)).lines

The first 3 lines is the scoring, a&b is is the score, f is the difference and the g is the function sastifying the specification.

Usage:

g"UUUuuuuuUUUuuUUUUUUuuuUUUuuUUUUuuuuUUUdddddddUU" -- 4

Akangka

Posted 2016-02-09T21:30:56.133

Reputation: 1 859

You can merge the two last lines and earn 1 byte: g=sum.map(\x->(10&x)-(5&x)).lines You can also remove the parentheses for another four bytes: g=sum.map(\x->10&x-5&x).lines – BlackCap – 2016-02-10T07:46:09.377

And 3 more bytes if you merge the map and the fold: a&b=foldl(\d g->min 200$d+a#g)0b – BlackCap – 2016-02-10T08:05:26.297

1

Lua, 196 Bytes

This program takes a single multi-line argument as input, and print the total difference in rep'

e,f,a=0,0,{u=10,U=10,d=-2}arg[1]:gsub(".-\n",function(s)x=0 y=0 s:gsub("[^\n]",function(c)t=x+a[c]x,t=t>199 and 200 or t,y+a[c]-(c<"V"and 5 or 0)y=t>199 and 200 or t end)e=e+x f=f+y end)print(e-f)

I assumed I am allowed to ask for a trailing new line in the input, if I'm not, here's a 204 Bytes solution that doesn't need it.

e,f,a=0,0,{u=10,U=10,d=-2}(arg[1].."\n"):gsub(".-\n",function(s)x=0 y=0 s:gsub("[^\n]",function(c)t=x+a[c]x,t=t>199 and 200 or t,y+a[c]-(c<"V"and 5 or 0)y=t>199 and 200 or t end)e=e+x f=f+y end)print(e-f)

Ungolfed and explanations

a={u=10,U=10,d=-2}            -- define the table containing the vote values
e,f=0,0                       -- initialize the total sums of rep'

arg[1]:gsub(".-\n",function(s)-- iterate over each line
  x=0                         -- score by the new scoring method for this UTC day
  y=0                         -- score by the old method
  s:gsub("[^\n]",function(c)  -- iterate over each non new-line character
    t=x+a[c]                  -- new score for today
    x=t>199 and 200 or t      -- reduce it to 200 if >=200
                        -- Do the same thing with the old scoring method
    t=y+a[c]-(c<"V"and 5 or 0)-- if c=="U", this question vote gives only 5
    y=t>199 and 200 or t      
  end)
  e=e+x f=f+y                 -- sum the scores over multiple days
end)
print(e-f)                    -- output the difference

Katenkyo

Posted 2016-02-09T21:30:56.133

Reputation: 2 857