Calculate your stack exchange reputation

Bash, 247 202 192 bytes

n=$1 bash <(sed 's/E/)echo /;s/C/ Aaccept/;s/A/answer /
s/.*)/((&)\&\&/'<<<'a=(n+1)/15,a-1)s=s;q=question
aE$aC$s
r=n%5,r-4)d=d&&
r>1E1Ced
1-r%2E1 Adownvote$d
n-=15*a,n>8)q=A
n>3E1 $q upvote')

How it works

After the sed command does it job, the following bash script gets executed:

((a=(n+1)/15,a-1))&&s=s;q=question
((a))&&echo $a answer accept$s
((r=n%5,r-4))&&d=d&&
((r>1))&&echo 1 answer accepted
((1-r%2))&&echo 1 answer downvote$d
((n-=15*a,n>8))&&q=answer 
((n>3))&&echo 1 $q upvote

To obtain the optimal solution (minimal number of events to get n reputation), it suffices to compute the number of accepted answers (a) necessary to get to a reputation below 16 (1 answer accept) and handle the residue as follows:

1  (no rep change)
2  answer accepted, answer downvoted
3  answer accepted
4  question upvote, answer downvote
5  question upvote, answer downvoted
6  question upvote
7  question upvote, answer accepted, answer downvoted
8  question upvote, answer accepted
9  answer upvote, answer downvote
10 answer upvote, answer downvoted
11 answer upvote
12 answer upvote, answer accepted, answer downvoted
13 answer upvote, answer accepted  
14 answer accept, answer downvote
15 answer accept, answer downvoted

Perl, 500 263 256 208 bytes

Script rep.pl:

$_=1+pop;sub P($){print$=,@_,$/}$;=" answer ";$:="$;downvote";($==$_/15)&&P"$;accept"."s"x($=>1);$_%=15;$==1;P"$;upvote",$_-=10if$_>9;P" question upvote",$_-=5if$_>4;P"$;accepted"if$_>2;P$:."d"if$_%2;P$:if!$_

Usage

The input is expected as positive integer, given as argument to the script. The different actions are output as lines.

Tests

perl rep.pl 11
1 answer upvote

perl rep.pl 93
6 answer accepts
1 answer accepted

perl rep.pl 1

perl rep.pl 4
1 question upvote
1 answer downvote

perl rep.pl 12
1 answer upvote
1 answer accepted
1 answer downvoted

perl rep.pl 19
1 answer accept
1 question upvote
1 answer downvote

perl rep.pl 34
2 answer accepts
1 question upvote
1 answer downvote

perl rep.pl 127
8 answer accepts
1 question upvote
1 answer accepted
1 answer downvoted

perl rep.pl 661266
44084 answer accepts
1 question upvote

Ungolfed

$_ = pop() + 1; # read the reputation as argument,
                # remove the actionless start reputation
                # and add a bias of two to calculate
                # the answer accepts in one division.

# Actions
# -------
# answer accepts:      Your answer is accepted    = +15
# answer upvotes:       Your answer is upvoted     = +10
# question upvotes:     Your question is upvoted   = +5
# answers accepted:     You accept an answer       = +2
# answers downvoted:    You downvote an answer     = -1
# answer downvotes:     Your answer is downvoted   = -2
# (questions downvoted: Your question is downvoted = -2) not used

# Function P prints the number of actions in $= and
# the action type, given in the argument.
# The function is prototyped "($)" to omit the
# parentheses in the usage.
sub P ($) {
    print $=, @_, $/ # $/ is the line end "\n"
}
# abbreviations,
# special variable names to save a space if a letter follows
$; = " answer ";
$: = "$;downvote";

# Calculation and printing the result
# -----------------------------------
($= = $_ / 15) && # integer division because of the special variable $=
P "$;accept" .
  "s" x ($= > 1); # short for: ($= == 1 ? "" : "s")
$_ %= 15;
$= = 1;           # now the action count is always 1 if the action is used
P "$;upvote",         $_ -= 10 if $_ > 9;
P " question upvote", $_ -=  5 if $_ > 4;
P "$;accepted"                 if $_ > 2;
P $: . "d"                     if $_ % 2;
P $:                           if ! $_

Older version

$_ = pop() + 1; # read the reputation as argument
                # subtract start reputation (1)
                # add bias (2)

# Actions
# -------
# $= answer accepts:      Your answer is accepted    = +15
# $b answer upvotes:      Your answer is upvoted     = +10
# $c question upvotes:    Your question is upvoted   = +5
# $d answers accepted:    You accept an answer       = +2
# $e answers downvoted:   You downvote an answer     = -1
# $f answer downvotes:    Your answer is downvoted   = -2
# -- questions downvoted: Your question is downvoted = -2

# Calculaton of answer accepts by a simple division that is
# possible because of the bias.
$= = $_ / 15; # integer division because of the special variable $=
$_ %= 15;

# The older version of the calculation can be simplified further, see below.
# Also the older version did not use the bias.
#
# function E optimizes the construct "$_ == <num>" to "E <num>"
# sub E {
#     $_ == pop
# }
#
# $d = $e = 1 if E 1;       #  1 =     +2 -1
# $d++ if E 2;              #  2 =     +2
#
# $c = $f = 1 if E 3;       #  3 =  +5 -2
# $c = $e = 1 if E 4;       #  4 =  +5 -1
# $c++ if E 5;              #  5 =  +5
# $c = $d = $e = 1 if E 6;  #  6 =  +5 +2 -1
# $c = $d = 1 if E 7;       #  7 =  +5 +2
#
# $b = $f = 1 if E 8;       #  8 = +10 -2
# $b = $e = 1 if E 9;       #  9 = +10 -1
# $b++ if E 10;             # 10 = +10
# $b = $d = $e = 1 if E 11; # 11 = +10 +2 -1
# $b = $d = 1 if E 12;      # 12 = +10 +2
#
# $=++, $f++ if E 13;       # 13 = +15 -2
# $=++, $e++ if E 14;       # 14 = +15 -1

$b++, $_ -= 10 if $_ > 9;
$c++, $_ -=  5 if $_ > 4;

# Now $_ is either 0 (-2), 1 (-1), 2 (0), 3 (1), or 4 (2).
# The number in parentheses is the remaining reputation change.

# The following four lines can be further optimized. 
# $f++        if ! $_;    # "! $_" is short for "$_ == 0"
# $e++        if $_ == 1;
# $d = $e = 1 if $_ == 3;
# $d++        if $_ == 4;

# Optimized version of the previous four lines:

$f++ if ! $_;
$e++ if $_ % 2;
$d++ if $_ > 2;

# function P optimizes the printing and takes the arguments for "print";
# the first argument is the action count and the printing is suppressed,
# if this action type is not needed.
sub P {
    print @_, $/ if $_[0]
    # $/ is "\n"
}

# some abbreviations to save some bytes
$; = " answer ";
$D = "$;downvote";

# output the actions

P $=, "$;accept", ($= == 1 ? "" : "s");
P $b, "$;upvote";
P $c, " question upvote";
P $d, "$;accepted";
P $e, $D, "d";
P $f, $D

Edits

  • Case 4 is fixed.
  • This also simplifies the calculation that is now done without a loop.
  • Unreachable plural "s" removed, function S no longer needed.
  • Calculation optimized, function E no longer needed.
  • Bias of 2 added for optimized calculation.
  • Larger rewrite to remove most variables some other tricks to save some bytes.

R, 454 421

r=as.integer(commandArgs(T)[1])-1;p=function(...){paste(...,sep='')};a='answer ';b='accept';e='ed';f='d';v='vote';d=p('down',v);u=p('up',v);q='question ';z=c();t=r%/%15;if(t>0){z=c(p(t,' ',a,b));r=r%%15;};if(r%in%(8:12))z=c(z,p(a,u));if(r%in%(3:7))z=c(z,p(q,u));if(r%in%c(1,2,6,7,11,12))z=c(z,p(a,b,e));if(r%in%(13:14))z=c(z,p(a,b));if(r%in%c(3,8,13))z=c(z,p(a,d));if(r%in%c(1,4,6,9,11,14))z=c(z,p(a,d,f));cat(z,sep=', ')

Thanks to Dennis for his answer which helped me a lot.

Ungolfed version

# read input
r = as.integer(commandArgs(T)[1]) - 1

# shortcut to join strings (... will pass the parameter to paste() *as is*)
p = function(...) {paste(..., sep = '')}

# strings
a = 'answer '; b = 'accept'; e = 'ed'; f = 'd'
v = 'vote'; d = p('down',v); u = p('up',v)
q = 'question '

z = c()

# +15
t = r %/% 15;
if (t > 0) {
    z = c(p(t,' ',a,b))
    r = r %% 15
}

if (r %in% (8:12))              z = c(z,p(a,u));    # answer upvote
if (r %in% (3:7))               z = c(z,p(q,u));    # question upvote
if (r %in% c(1,2,6,7,11,12))    z = c(z,p(a,b,e));  # answer accepted
if (r %in% (13:14))             z = c(z,p(a,b));    # answer accept
if (r %in% c(3,8,13))           z = c(z,p(a,d));    # answer downvote
if (r %in% c(1,4,6,9,11,14))    z = c(z,p(a,d,f));  # answer downvoted

# print operations
cat(z,sep = ', ')

Tags:

Code Golf