How much reputation does a steam user have?

20

4

Introduction

For those not familiar with steam - or at least this particular aspect:

Often on peoples' profiles, people leave comments saying either "+rep _____" or "-rep _____". These are an unofficial means of showing whether you think someone in the community has a good or a bad reputation, for a number of reasons. Such comments look like:

+rep a good player

+rep helpful

-rep hacker

-rep scammer


Task

The program must take input through any consensual way. The input consists of a string with optional newlines (\n). At the very start of each line, '+rep ' or '-rep ' might be present. The rest of the line can be discarded. If the line doesn't start with '+rep ' or '-rep ' (note the trailing space), the line should be ignored.

The program then must keep a total reputation score. Starting at 0, this score should be incremented on every line that starts with '+rep ' and decremented on every line that starts with '-rep '.

This result should be output in any agreed-upon way.


Test cases

Input:
+rep fast trade
+rep nice person
-rep too good

Output: 1

Input:
-rep hacker
-rep scammer
-rep was mean

Output: -3

Input:
first
i don't like him
+rep good at cs go

Output: 1

Input (note the lack of a trailing space on the third line):    
+rep +rep
hi +rep
-rep

Output: 1

Input:
+ rep

Output: 0

Input:
+rep like
-thing

Output: 1

Bonus

I don't even know if it's possible, but bonus points if you can somehow get these comments from Steam.

Jacob Garby

Posted 2017-04-10T13:38:39.960

Reputation: 350

Question was closed 2017-04-11T16:53:50.327

5Assuming the bonus points are imaginary, correct? They don't actually affect your score. – Rɪᴋᴇʀ – 2017-04-10T13:39:40.987

Will we ever get empty input? What about no occurrences of +/-rep? Will +/-rep always have a trailing space? – user41805 – 2017-04-10T13:43:35.133

2Can we assume the only plus and minus signs are in the '+rep'/'-rep'? Will the rep only be at the start of the line, or could it be in the middle also? – Rɪᴋᴇʀ – 2017-04-10T13:44:23.637

@Riker "Each line of the text will start with either "+rep" or "-rep". The rest of the line could contain anything." – HyperNeutrino – 2017-04-10T13:45:00.083

dupe? – Matthew Roh – 2017-04-10T13:57:46.767

3I would recommend adding a test case where there is a +rep or -rep that isn't at the start of the line – fəˈnɛtɪk – 2017-04-10T14:13:52.600

s/+rep.*/1 and s/-rep.*/\x08? – Matthew Roh – 2017-04-10T14:49:21.330

Will the input contain any other symbols other than + and -? – user41805 – 2017-04-10T14:49:31.647

What is the set of characters the input will contain? – user41805 – 2017-04-10T15:01:19.103

1Okay: The bonus points are imaginary The input can be empty, in which case the output will be 0 +/-rep will always have a trailing space It is codegolf The +/- signs are not necessarily in the rep The +/-rep must be at the start of a line – Jacob Garby – 2017-04-10T15:33:29.983

@JacobGarby What does +rep output? – user41805 – 2017-04-10T15:39:10.343

@KritixiLithos 1 – Jacob Garby – 2017-04-10T15:41:29.300

@JacobGarby But you said that rep will always have a trailing space, yet the testcase I provided does not seem to fit that rule – user41805 – 2017-04-10T15:47:35.203

@KritixiLithos True... In which case no, +rep would output 0 – Jacob Garby – 2017-04-10T15:50:26.067

We aim for a strict definition of the rules so that there aren't 500 different interpretations. – fəˈnɛtɪk – 2017-04-10T15:51:28.567

By this point, there are very few interpretations, with very little variation between them. But okay - I think I've cleared everything up now. – Jacob Garby – 2017-04-10T15:53:42.877

3I believe that example 4 should have output 0, not 1. – James – 2017-04-10T17:54:52.773

10

Hi Jacob, and welcome to PPCG. You've managed to get a quite active conversation for your first challenge here! Since no one else has yet mentioned it, I'll direct you to the Sandbox where you can get meaningful feedback and hammer out any details or clarification issues before posting the challenge to Main. In the future, that will help you avoid downvotes, closevotes, and the like. I hope you stick around and enjoy your stay!

– AdmBorkBork – 2017-04-10T18:02:28.853

What about +rep -rep? – BlueRaja - Danny Pflughoeft – 2017-04-10T18:45:43.723

The spec says that there isn't any need for a trailing space, 3rd test case and you are saying the opposite. Please update the post accordingly to what you meant. – dzaima – 2017-04-10T19:16:20.720

Hey everyone, I'd like to kinda hijack the comments and note down that the reputation comments usually don't mean much as malicious people can and do pay people in items to post +rep comments to their profile. Stay safe! – Ave – 2017-04-11T16:32:25.987

Answers

9

05AB1E, 18 16 17 bytes

Saved 2 bytes thanks to Okx
+1 byte due to change in spec where rep now need to be followed by a space.

|vy5£„+-S„·Ý «QÆO

Try it online!

Explanation

|v                   # for each line of input
  y5£                # get the first 4 chars of input
     „+-S„·Ý «       # push the list ['+rep ','-rep ']
              Q      # check each for equality
                     # results in either [1,0] for +rep, [0,1] for -rep or [0,0] for others
               Æ     # reduce by subtraction, gives either 1, -1 or 0
                O    # sum

Emigna

Posted 2017-04-10T13:38:39.960

Reputation: 50 798

You can replace ð¡0è with . I was working on a solution to this at the same time you were. – Okx – 2017-04-10T16:19:38.380

@Emigna I feel like my idea of |ðý#D'·Ý©.åÏ®1:O can be 14 or 15, I'm just not seeing it. Also stuck at 16, maybe it will help you though. I'll leave it here. Basically replacing the word "rep" with the number "1" so you can direct sum. – Magic Octopus Urn – 2017-04-10T17:03:47.247

@carusocomputing: I think I have it at 14 yes. Just gotta some more tests :) – Emigna – 2017-04-10T17:06:55.530

Better to beat the inevitable Jelly tie before it happens ;). – Magic Octopus Urn – 2017-04-10T17:08:01.463

@carusocomputing: actually my way 0|vy4£'·Ý1:R.V doesn't work for lines not starting with +/- rep. Back to the drawing board :( – Emigna – 2017-04-10T17:08:58.513

I think it's actually 17 bytes: |vy5£„+-S„·Ý «QÆO, since you need to check for the space after rep too. – Erik the Outgolfer – 2017-04-10T17:11:08.827

@carusocomputing Jelly is highly unlikely to beat 05AB1E here. – Erik the Outgolfer – 2017-04-10T17:15:44.243

@EriktheOutgolfer: Yeah that seems to have been edited in to the question as someone was asking to have it... :/ – Emigna – 2017-04-10T17:19:08.607

@Emigna fəˈnɛtɪk edited it in. – Erik the Outgolfer – 2017-04-10T17:24:08.517

@EriktheOutgolfer I edited it in but it was already specified by the OP. "The input can be empty, in which case the output will be 0 +/-rep will always have a trailing space It is codegolf The +/- signs are not necessarily in the rep The +/-rep must be at the start of a line" – Jacob Garby – fəˈnɛtɪk – 2017-04-10T17:26:57.387

I don't think mine is affected by the change, so you can use |ðý#D'·Ý©.åÏ®1:O for 16 if you like; because it's splitting on spaces, the space is accounted for. Half of that was inspired by this answer anyhow. – Magic Octopus Urn – 2017-04-10T17:58:22.817

@carusocomputing: Unfortunately, that counts rep's which are not at the start of the line as well. I like the idea of using the operations from the input together with 1, but I haven't found a way to modify it below 17. – Emigna – 2017-04-10T18:16:53.513

10

Python 3, 73 bytes

I'm sure this answer is garbage and will be beaten soon, but there's no other python answers yet

lambda x:sum(["- +".index(i[0])-1for i in x.split('\n')if i[1:4]=="rep"])

Use like this:

f = lambda x:sum(["- +".index(i[0])-1for i in x.split('\n')if i[1:4]=="rep"])
print(f("PUT INPUT HERE"))


Fetching from steam

Here's some sample code which fetches the first 100 comments from KennyS' profile and calculates his rep.

import requests
from bs4 import BeautifulSoup

# Kenny's profile as Steam ID 64
# You can adjust this to whatever numbers you want
STEAM_PROFILE_URL = "76561198024905796"
payload =  {"start" : 0, "count" : 100}
r = requests.post("http://steamcommunity.com/comment/Profile/render/{}/-1/".format(STEAM_PROFILE_URL), payload)

# Comments are html inside a json object
soup = BeautifulSoup(r.json()["comments_html"], "html.parser")

# Get raw text for every comment.
# The " ".join() strips out the newlines and tabs which are part of html
comments = [" ".join(s.text.split()) for s in soup.find_all("div", {"class" : "commentthread_comment_text"})]

calculateRep = lambda x:sum(["- +".index(i[0])-1for i in x.split('\n')if i[1:4]=="rep"])

print(calculateRep("\n".join(comments)))

Keatinge

Posted 2017-04-10T13:38:39.960

Reputation: 481

if"rep"==i[1:4] for -1 – ovs – 2017-04-11T13:57:25.713

You don't need the square brackets – ovs – 2017-04-11T15:23:37.360

9

Perl 5, 25 bytes

24 bytes of code + -p flag.

$\+=/^\+rep /-/^-rep /}{

Try it online!

/^\+rep / returns 1 if the line starts with +rep; /^-rep / returns 1 if the line starts with -rep (so only one of them will be one at most). We use $\ to store the result, as it is implicitly printed at the end (thanks to -p flag and those unmatched }{).

Dada

Posted 2017-04-10T13:38:39.960

Reputation: 8 279

Add two bytes because there needs to be a space after rep – fəˈnɛtɪk – 2017-04-10T16:32:32.630

This doesn't seem very clear from the spec but since pretty much everyone is doing it, I'll edit that as soon as I get my hands on a computer. – Dada – 2017-04-10T16:44:00.020

I added it to the specs because the OP had left it as a comment – fəˈnɛtɪk – 2017-04-10T16:46:17.710

6

Python 2, 54 bytes

q=('\n'+input()).count;print q('\n+rep ')-q('\n-rep ')

Try it online! Takes a multiline string as input.

Counts the appearances of '+rep ' and '-rep ' only at starts of lines by searching for the string following a newline symbol. To catch the first line, a newline is prepended to the input.

xnor

Posted 2017-04-10T13:38:39.960

Reputation: 115 687

5

Retina, 63 51 50 49 bytes

Didn't quite comply with the spec so I fixed some issues but also golfed it a lot (by borrowing the first line from Kritixi Lithos's solution).

Saved another byte thanks to Kritixi Lithos.

ms`(?!^[+-]rep ).

+`\+-|-\+

(.)+
$1$.&
T`+
$^
0

Try it online!

Explanation

ms`(?!^[+-]rep ).

First, everything from the input is deleted, except for the + and - from any +rep or -rep at the start of a line.

+`\+-|-\+

Then adjacent pairs of + and - are removed until no more can be removed. After this, what's left is either a run of +s, a run of -s, or nothing.

(.)+
$1$.&

Then a run of one or more characters (either + or -) is replaced with the character making up the run followed by the length of the run. This way, + is preserved at the start for positive results and - for negatives.

T`+

Then all +s are removed, in the event that the rep is positive.

$^
0

Finally, if the string is empty at this point, the rep is 0, so we write 0.

Business Cat

Posted 2017-04-10T13:38:39.960

Reputation: 8 927

You can do drop the and add a s (single-line mode) after the m on the first line – user41805 – 2017-04-10T16:15:13.760

4

JavaScript, 55 bytes

Thanks @Neil for golfing off 12 bytes Thanks @Arnauld for golfing off 2 bytes

x=>x.split(/^\+rep /m).length-x.split(/^-rep /m).length

Try it online!

var y=x=>(x.match(/^\+rep /gm)||'').length-(x.match(/^-rep /gm)||'').length

document.querySelector('div').innerText=y(document.querySelector('textarea').value)
textarea{
  width: 95%;height: 100px;
  }
<textarea oninput = "document.querySelector('div').innerText=y(this.value)">
-rep Cheater!!
+rep very good, fun to play with
+rep my friend +rep
good
</textarea>
<div></div>

fəˈnɛtɪk

Posted 2017-04-10T13:38:39.960

Reputation: 4 166

Save 12 bytes by using split instead of match (it always returns an array which is 1 longer that you normally want but the two 1s cancel). I also tried to eliminate the duplication but it came out at 57 bytes again. – Neil – 2017-04-11T00:41:40.053

3

PHP, 118 bytes

function s($a,$c=0){foreach(explode("
",$a)as$b){$b=substr($b,0,1).'1';if(is_numeric($b){$c+=$b});}return$c-($a=="");}

Try it online!

Used like this:

echo s("-rep bad
+rep good
+rep very good
+rep exceeds expectation");

steenbergh

Posted 2017-04-10T13:38:39.960

Reputation: 7 772

This outputs 1 if you feed it the empty string – fəˈnɛtɪk – 2017-04-10T16:30:51.530

@fəˈnɛtɪk fixed – steenbergh – 2017-04-10T16:47:31.267

Would recommend fixing your link. It also errors after outputting if you give it a non +/-rep line :P – fəˈnɛtɪk – 2017-04-10T16:51:52.600

3

Retina, 59 53 52 50 bytes

ms`(?!^[+-]rep ).

+`\+-|-\+

-+
-$.&
\++
$.&
^$
0

Try it online!

Check out Basic Sunset's shorter answer in the same language!

Explanation

ms`(?!^[+-]rep ).

Removes everything except for [+-]reps.

+`\+-|-\+

Repeatedly removes 1 - for every + and vice versa.

-+
-$.&

Prepend a - (because the number is negative) to -s as well as replacing the -s with the number of -s.

\+
$.&

Do the same for +s, but don't prepend a -.

^$
0

Finally, if there is nothing, replace it with a 0.

user41805

Posted 2017-04-10T13:38:39.960

Reputation: 16 320

@fəˈnɛtɪk > +/-rep will always have a trailing space

– user41805 – 2017-04-10T16:19:07.030

OK so I edited that into the actual question. – fəˈnɛtɪk – 2017-04-10T16:21:26.847

3

Mathematica, 47 bytes (ISO 8859-1 encoding)

(±c_:=StringCount["
"<>#,c];±"
+rep"-±"
-rep")&

Pure function taking a newline-separated string as input and returning an integer. Note that the three newlines in the code are flanked by quotes and are thus each equivalent to "\n" in a string (but this way is one byte shorter than "\n"). StringCount does the heavy lifting; we manually add a newline to the beginning of the string so that the first line matches when appropriate. ± is a unary helping function to avoid repetition of StringCount.

The alternative solution

(±c_:=StringCount["
"<>#,"
"<>c<>"rep"];±"+"-±"-")&

is 4 bytes longer, but I do like the sequence ±"+"-±"-"....

Greg Martin

Posted 2017-04-10T13:38:39.960

Reputation: 13 940

I think you might need to add a space behind the +/-rep as that was apparently part of the requirements – fəˈnɛtɪk – 2017-04-10T17:09:36.867

3

Röda, 53 bytes

{{|l|[1]if[l=~`\+rep .*`];[-1]if[l=~`-rep .*`]}_|sum}

Try it online!

fergusq

Posted 2017-04-10T13:38:39.960

Reputation: 4 867

1

Java, 109 bytes

l->{int i=0;for(String s:l.split("\n")){if(s.startsWith("+rep "))i++;if(s.startsWith("-rep "))i--;}return i;}

Trying to make this shorter using Stream's

Roman Gräf

Posted 2017-04-10T13:38:39.960

Reputation: 2 915

Needs a space after rep – fəˈnɛtɪk – 2017-04-10T17:59:45.563

1

Stacked, 45 bytes

'^([+-])rep |.'{.a:''['#'a+]a if}mrepl'0'\+#~

Try it online!

Alternatively (49 bytes):

lines'^[-+]rep 'match$#'YES[0#0# '#'\+]"!''#`0\#~

Explanation

'^([+-])rep |.'{.a:''['#'a+]a if}mrepl'0'\+#~

This basically extracts all + or - attached to the beginning of the line and rep. Then, to each, it prepends a #. Then, to the entire thing, a 0 is prepended. #~ evaluates the string, which now looks something like:

0#+#+#-

#+ is increment and #- is decrement. Thus, we obtain our desired result.

Conor O'Brien

Posted 2017-04-10T13:38:39.960

Reputation: 36 228

1

Retina, 38 bytes

M!m`^[+-]rep 
Os`.
+`\+-

*\M1!`-
[+-]

Try it online!

A different (and shorter) solution than the ones already posted in Retina.

Explanation

M!m`^[+-]rep 

(This line has a trailing space). Keep only the relevant parts of the input, i.e. the +rep or -rep at the beginning of a line.

Os`.

Sort all characters (including newlines). this will put +s and -s next to each other.

+`\+-

Repeatedly remove +- couples until at most one of the two signs remains.

*\M1!`-

Match the first - (if present) and print it without modifying the string.

[+-]

Count the number of signs remaining, and print it since this is the final stage of the program.

Leo

Posted 2017-04-10T13:38:39.960

Reputation: 8 482

0

JavaScript ES6, 85 79 bytes

l=>eval(l.split`
`.map(i=>(r=i.slice(0,5))==`+rep `?1:r==`-rep `?-1:0).join`+`)

Try it

f=l=>eval(l.split`
`.map(i=>(r=i.slice(0,5))==`+rep `?1:r==`-rep `?-1:0).join`+`);

console.log(f(`+rep fast trade
+rep nice person
-rep too good`));

console.log(f(`-rep hacker
-rep scammer
-rep was mean`));

console.log(f(`first
i don't like him
+rep good at cs go`));

console.log(f(`+rep +rep
hi +rep
-rep`));

console.log(f(`+ rep`));

console.log(f(`+rep like
-thing`));


Ungolfed

const repcount=list=>{
    let array=list.split("\n");
    let values=array.map(item=>{
        let rep=item.slice(0,5);
        return rep==="+rep "?1:rep==="-rep "?-1:0;
    });
    let result=values.reduce((a,b)=>a+b);
    return result;
};

History

85 bytes

l=>l.split`\n`.map(i=>(r=i.slice(0,5))=="+rep "?1:r=="-rep "?-1:0).reduce((a,b)=>a+b)

Shaggy

Posted 2017-04-10T13:38:39.960

Reputation: 24 623

0

C#, 87 bytes

s=>{int n=0;foreach(var t in s.Split('\n'))n+=t.IndexOf("rep ")==1?44-t[0]:0;return n;}

Anonymous function which splits the input string by using the newline character, searches for the "rep " string prefixed by a character and, if it finds it, increments the reputation (the n variable) by 1 or -1.

Full program with ungolfed method and test cases:

using System;

class P
{
    static void Main()
    {
        Func<string, int> f =
        s=>
        {
            int n = 0;
            foreach (var t in s.Split('\n'))
                n += t.IndexOf("rep ") == 1 ?
                    44 - t[0]
                    :
                    0;

            return n;
        };

        // test cases:
        Console.WriteLine(f(@"+rep fast trade
+rep nice person
-rep too good"));       // 1

        Console.WriteLine(f(@"-rep hacker
-rep scammer
-rep was mean"));       // -3

        Console.WriteLine(f(@"first
i don't like him
+rep good at cs go"));  // 1

        Console.WriteLine(f(@"+rep +rep
hi +rep
-rep"));            // 1

        Console.WriteLine(f(@"+ rep"));     // 0

        Console.WriteLine(f(@"+rep like
-thing"));          // 1
    }
}

Note that the ASCII code for + is 43 and for - is 45. This method passes all test cases from the OP. However, if the first character is something else, this will lead to wrong answers!

This can be fixed at the cost of 17 bytes:

C# fixed, 104 bytes

s=>{int n=0;foreach(var t in s.Split('\n'))n+=t.IndexOf("rep ")==1?t[0]==43?1:t[0]==45?-1:0:0;return n;}

The modified anonymous function will check for a + or - sign as the first character in each line.

adrianmp

Posted 2017-04-10T13:38:39.960

Reputation: 1 592

0

Japt, 14 bytes

r`œp`1 f".%d 

Try it online!

+1 byte for -x flag

Tom

Posted 2017-04-10T13:38:39.960

Reputation: 3 078

0

C++, 144 bytes

#import<iostream>
int f(){int r=0;for(std::string s;std::getline(std::cin,s);)if((s[0]==43|s[0]==45)&s.substr(1,4)=="rep ")r-=s[0]-44;return r;}

Try it online!

Steadybox

Posted 2017-04-10T13:38:39.960

Reputation: 15 798

0

Ruby, 46 bytes

->x{rep=1;eval ?0+x.map{|a|a[/^[+-]rep /]}*''}

Get all the +/-rep from input, and put together in a single string. Then evaluate that for rep=1.

G B

Posted 2017-04-10T13:38:39.960

Reputation: 11 099

0

C#, 104 bytes


Despite existing already one solution -- and mine being longer -- I still think I should post it, since the on already here might fail if something like '=rep ' gets in it's way.


Golfed

i=>{var c=0;foreach(var o in i.Split('\n'))c+=o.IndexOf("rep ")!=1?0:o[0]==43?1:o[0]==45?-1:0;return c;}

Ungolfed

i => {
   var c = 0;

   foreach( var o in i.Split( '\n' ) )
      c += o.IndexOf( "rep " ) != 1
         ? 0
         : o[ 0 ] == 43
            ? 1
            : o[ 0 ] == 45
               ? -1
               : 0;

   return c;
}

Ungolfed readable

i => {
   // Counter for the 'reputation'
   var c = 0;

   // Cycle through every line
   foreach( var o in i.Split( '\n' ) )
      // Check if the "rep " string has index 1
      //   ( Index 0 should be the sign )
      c += o.IndexOf( "rep " ) != 1
         // Add 0 if the rep isn't on the right position
         ? 0
         // Check for the '+' sign
         : o[ 0 ] == 43
            // Add 1 if the sign is found
            ? 1
            // Check for the '-' sign
            : o[ 0 ] == 45
               // Add -1 if the sign is found
               ? -1
               // Add 0 if another char is found
               : 0;

   // Return the 'reputation'
   return c;
}

Full code

using System;
using System.Collections.Generic;

namespace Namespace {
   class Program {
      static void Main( String[] args ) {
         Func<String, Int32> f = i => {
            var c = 0;

            foreach( var o in i.Split( '\n' ) )
               c += o.IndexOf( "rep " ) != 1
               ? 0
                  : o[ 0 ] == 43
                  ? 1
                  : o[ 0 ] == 45
                     ? -1
                     : 0;

            return c;
         };

         List<String>
            testCases = new List<String>() {
               @"+rep fast trade
+rep nice person
-rep too good",
               @"-rep hacker
-rep scammer
-rep was mean",
               @"first
i don't like him
+rep good at cs go",
               @"+rep +rep
hi +rep
-rep",
               @"+ rep",
               @"+rep like
-thing",
         };

         foreach( String testCase in testCases ) {
            Console.WriteLine( $"{testCase}\n{f( testCase )}\n" );
         }

         Console.ReadLine();
      }
   }
}

Releases

  • v1.0 - 104 bytes - Initial solution.

Notes

Nothing to add

auhmaan

Posted 2017-04-10T13:38:39.960

Reputation: 906