SE投稿で上位5つのコメントスコアを表示する


30

Stack Exchangeスクリプトは、サイトのメインページに最初に表示される質問または回答に関する5つのコメントを、それらへの賛成票の数によって決定します。投票数が最も多い5つのコメントが表示されます。あなたの仕事は、この動作を再現することです。

STDIN、コマンドライン引数、または関数の引数を使用して入力を取得する完全なプログラムまたは関数を作成し、上位5つのコメントスコアを出力または返します。入力は、ある投稿のコメントに対する賛成票の数を表す整数の配列になります。たとえば、の入力

0, 2, 5, 4, 0, 1, 0

は、最初のコメントには投票がなく、2番目のコメントには2票、3番目には5票、4番目には4票、というようになります。

入力に含まれるコメントスコアが5つ以下の場合、出力には指定されたもののみが含まれます。2つ以上のコメントスコアが同じ場合、最初のスコアが表示されます。入力配列には、少なくとも1つのコメントスコアが含まれると想定できます。

出力内の番号は簡単に区別できるはずです(したがって、ケース1の02541は無効です)。それ以外の場合、出力形式に制限はありません。数字はスペースまたは改行で区切られているか、リスト形式などになっている場合があります。

テストケース:

[0, 2, 5, 4, 0, 1, 0] -> [0, 2, 5, 4, 1]
[2, 1, 1, 5, 3, 6] -> [2, 1, 5, 3, 6]
[0, 4, 5] -> [0, 4, 5]
[1, 1, 5, 1, 1, 5] -> [1, 1, 5, 1, 5]
[0, 2, 0, 0, 0, 0, 0, 0] -> [0, 2, 0, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 0, 0] -> [0, 0, 0, 0, 1]
[5, 4, 2, 1, 0, 8, 7, 4, 6, 1, 0, 7] -> [5, 8, 7, 6, 7]
[6, 3, 2, 0, 69, 22, 0, 37, 0, 2, 1, 0, 0, 0, 5, 0, 1, 2, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 2] -> [6, 69, 22, 37, 5]

最後の例は、このStack Overflowの質問から引用したものです。

可能であれば、投稿をオンラインで実行できるリンクを投稿に提供してください。

これはコードゴルフであるため、バイト単位の最短コードが優先されます。がんばろう!


順序を維持する必要がありますか?
コナーオブライエン

@CᴏɴᴏʀO'Bʀɪᴇɴはい。整数が表示される順序は変更しないでください。
TNT

回答:


10

ゼリー、6 バイト

NỤḣ5Ṣị

オンラインでお試しください!または、すべてのテストケースを一度に検証します

使い方

NỤḣ5Ṣị    Main link. Input: A (list)

N         Negate (multiply by -1) all elements of A.
 Ụ        Grade the result up.
          This consists in sorting the indices of A by their negated values.
          The first n indices will correspond to the n highest vote counts,
          tie-broken by order of appearance.
  ḣ5      Discard all but the first five items.
    Ṣ     Sort those indices.
          This is to preserve the comments' natural order.
     ị    Retrieve the elements of A at those indices.

10

Python 2、58バイト

x=input()[::-1]
while x[5:]:x.remove(min(x))
print x[::-1]

Ideoneでテストします。

使い方

list.remove引数が指定されたリストからある場合、最初の出現を削除します。リストxを逆にすることで、最後の出現を削除することを本質的に達成します。

したがって、5つ以下のコメントのリストに達するまで、最小限の賛成票でコメントを削除し続けるだけで十分です。その後、リストをもう一度逆にして元の順序に戻します。


9

Pyth、11バイト

_.-_Q<SQ_5

入力(Q)の5つの最大要素とのマルチセット交差を(Qそれらが現れる順序でQ)計算し、それらの最初の5つを取得します。

_ .-           Reverse of multiset difference
     _ Q       of reversed Q
     <         with all but last 5 elements of sorted Q
       S Q                   
       _ 5

ここで試してみてください


<5SQ is equivalent to <SQ_5, which saves 1 byte.
PurkkaKoodari


Interesting. I wonder why it's not implemented as b[:-a]... I think it even might've been that at some point.
PurkkaKoodari

5

MATL, 16 bytes

tn4>?t_FT#S5:)S)

This uses current release (10.2.1), which is earlier than this challenge.

Try it online!

Explanation

          % implicitly get input
t         % duplicate
n         % number of elements
4>?       % if greater than 4...
  t       % duplicate
  _       % unary minus (so that sorting will correspond to descending order)
  FT#S    % sort. Produce the indices of the sorting, not the sorted values
  5:)     % get first 5 indices
  S       % sort those indices, so that they correspond to original order in the input
  )       % index the input with those 5 indices
          % implicitly end if
          % implicitly display

5

JavaScript, 74 65 62 61 bytes

3 bytes off thanks @user81655. 1 byte off thanks @apsillers.

f=a=>5 in a?f(a.splice(a.lastIndexOf(Math.min(...a)),1)&&a):a


5

Python 3, 76

Saved 9 bytes thanks to Kevin reminding me that I can abuse if statements in a list comp.

Saved 5 bytes thanks to DSM.

Pretty simple solution right now. Grab the top 5 scores and then parse through the list adding them to the result as we find them.

def f(x):y=sorted(x)[-5:];return[z for z in x if z in y and not y.remove(z)]

Here are my test cases if anyone wants them:

assert f([0, 2, 5, 4, 0, 1, 0]) == [0, 2, 5, 4, 1]
assert f([2, 1, 1, 5, 3, 6]) == [2, 1, 5, 3, 6]
assert f([0, 4, 5]) == [0, 4, 5]
assert f([0, 2, 0, 0, 0, 0, 0, 0]) == [0, 2, 0, 0, 0]
assert f([0, 0, 0, 0, 1, 0, 0, 0, 0]) == [0, 0, 0, 0, 1]
assert f([5, 4, 2, 1, 0, 8, 7, 4, 6, 1, 0, 7]) == [5, 8, 7, 6, 7]
assert f([6, 3, 2, 0, 69, 22, 0, 37, 0, 2, 1, 0, 0, 0, 5, 0, 1, 2, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 2]) == [6, 69, 22, 37, 5]

4

05AB1E, 12 11 bytes

Code:

E[Dg6‹#Rß\R

Explanation:

E           # Evaluate input
 [          # Infinite loop
  D         # Duplicate top of the stack
   g        # Get the length
    6‹#     # If smaller than 6, break
       R    # Reverse top of the stack
        ß\  # Extract the smallest item and remove it
          R # Reverse top of the stack
            # Implicit, print the processed array

Uses CP-1252 encoding.


4

CJam, 16 bytes

{ee{1=~}$5<$1f=}

An unnamed block (function) that takes an array and returns an array.

Test suite.

Explanation

ee   e# Enumerate the array, pairing each number with its index.
{    e# Sort by...
 1=  e#   The original value of each element.
 ~   e#   Bitwise NOT to sort from largest to smallest.
}$   e# This sort is stable, so the order tied elements is maintained.
5<   e# Discard all but the first five.
$    e# Sort again, this time by indices to recover original order.
1f=  e# Select the values, discarding the indices.


3

Python, 68 bytes

lambda l,S=sorted:zip(*S(S(enumerate(l),key=lambda(i,x):-x)[:5]))[1]

Example run.

A lump of built-ins. I think the best way to explain is to run through an example.

>> l
[5, 4, 2, 1, 0, 8, 7, 4, 6, 1, 0, 7]
>> enumerate(l)
[(0, 5), (1, 4), (2, 2), (3, 1), (4, 0), (5, 8), (6, 7), (7, 4), (8, 6), (9, 1), (10, 0), (11, 7)]

enumerate turns the list into index/value pairs (technically an enumerate object).

>> sorted(enumerate(l),key=lambda(i,x):-x)
[(5, 8), (6, 7), (11, 7), (8, 6), (0, 5), (1, 4), (7, 4), (2, 2), (3, 1), (9, 1), (4, 0), (10, 0)]
>> sorted(enumerate(l),key=lambda(i,x):-x)[:5]
[(5, 8), (6, 7), (11, 7), (8, 6), (0, 5)]

The pairs are sorted by greatest value first, keeping the current order of index for ties. This puts at the front the highest-scored comments, tiebroken by earlier post. Then, the 5 best such comments are taken.

>> sorted(_)
   [(0, 5), (5, 8), (6, 7), (8, 6), (11, 7)]
>> zip(*sorted(_))[1]
   (5, 8, 7, 6, 7)

Put the top five comments back in posting order, and then remove the indices, keeping only the scores.


3

PowerShell v4, 120 97 bytes

param($a)$b=@{};$a|%{$b.Add(++$d,$_)};($b.GetEnumerator()|sort Value|select -l 5|sort Name).Value

Experimenting around, I found an alternate approach that golfed off some additional bytes. However, it seems to be specific to PowerShell v4 and how that version handles sorting of a hashtable -- it seems, by default, that in v4 if multiple Values have the same value, it takes the one with a "lower" Key, but you're not guaranteed that in v3 or earlier, even when using the ordered keyword in v3. I've not fully vetted this against PowerShell v5 to say if the behavior continues.

This v4-only version takes input as $a, then creates a new empty hashtable $b. We loop through all the elements of the input $a|%{...} and each iteration add a key/value pair to $b (done by pre-incrementing a helper variable $d as the key for each iteration). Then we sort $b based on Value, then select the -last 5, then sort by Name (i.e., the key), and finally output only the .Values of the resultant hash.

If fewer than 5 elements are entered, it will just sort on value, select the last five (i.e., all of them), re-sort on key, and output.


Older, 120 bytes, works in earlier versions

param($a)if($a.Count-le5){$a;exit}[System.Collections.ArrayList]$b=($a|sort)[-5..-1];$a|%{if($_-in$b){$_;$b.Remove($_)}}

Same algorithm as Morgan Thrapp's answer, which is apparently an indication that great minds think alike. :)

Takes input, checks if the number of items is less-than-or-equal-to 5, and if so outputs the input and exits. Otherwise, we create an ArrayList $b (with the exorbitantly lengthy [System.Collections.ArrayList] cast) of the top five elements of $a. We then iterate over $a and for each element if it's in $b we output it and then remove it from $b (and here's why we need to use ArrayList, as removing elements from an Array isn't a supported feature in PowerShell, since they're technically fixed size).

Requires v3 or greater for the -in operator. For an answer that works in earlier versions, swap $_-in$b for $b-contains$_ for a total of 126 bytes.


2

Haskell, 62 bytes

import Data.List
map snd.sort.take 5.sortOn((0-).snd).zip[0..] 

Usage example: map snd.sort.take 5.sortOn((0-).snd).zip[0..] $ [5, 4, 2, 1, 0, 8, 7, 4, 6, 1, 0, 7] -> [5,8,7,6,7].

How it works: augment each element with it's index, sort descending, take first 5 elements, sort by index and remove index.


2

PHP 5, 107 102

Saved 5 bytes thanks to @WashingtonGuedes

function p($s){uasort($s,function($a,$b){return$a<=$b;});$t=array_slice($s,0,5,1);ksort($t);return$t;}

Ungolfed

function p($scores) {
    // sort the array from high to low,
    // keeping lower array keys on top of higher
    // array keys
    uasort($scores,function($a, $b){return $a <= $b;});
    // take the top 5
    $top_five = array_slice($scores,0,5,1);
    // sort by the keys
    ksort($top_five);
    return $top_five;
}

Try it.


For 1 1 5 1 1 5, your submission produces an output of 1 5 1 1 5 instead of the correct 1 1 5 1 5.
TNT

It seems to behave differently for PHP 7.X, switch the PHP version to 5.6 or below.
Samsquanch

Gotcha, didn't notice the version number. :)
TNT

I didn't either at first. I'm not sure why that doesn't save what version used as well as the code. I'm also not sure why it doesn't work correctly on 7.X.
Samsquanch

@WashingtonGuedes Removing spaces saved me 5 bytes, but I'm not seeing any unnecessary semicolons that wouldn't throw an error?
Samsquanch

0

Ruby, 82 87 89 bytes

$><<eval($*[0]).map.with_index{|x,i|[i,x]}.sort_by{|x|-x[1]}[0,5].sort.map(&:last)

to call: ruby test.rb [1,2,2,3,4,5]

original submission - 56 bytes but fails on certain test cases & didn't support $stdin and $stdout

_.reduce([]){|a,x|a+=_.sort.reverse[0..4]&[x]if !a[4];a}

Explanation

$><<               # print to stdout
eval($*[0])        # evals the passed in array in stdin ex: [1,2,3,4]
.map.with_index    # returns an enumerator with indices
{|x,i|[i,x]}       # maps [index,value]
.sort_by{|x|-x[1]} # reverse sorts by the value
[0,5]              # selects the first 5 values
.sort              # sorts item by index (to find the place)
.map{|x|x[1]}      # returns just the values

Nice program. You might have to ask the OP about that though. I am not sure the input format is okay.
Rɪᴋᴇʀ

@RikerW it actually fails when there is a duplicate top # in the last indice, I'm modifying it now
John

@RikerW its fixed now, and it supports stdin and writes to stdout.
John

Okay. I like the input method though. I was just saying to ask @TNT about it.
Rɪᴋᴇʀ

0

Java 7, 155 bytes

import java.util.*;List c(int[]f){LinkedList c=new LinkedList();for(int i:f)c.add(i);while(c.size()>5)c.removeLastOccurrence(Collections.min(c));return c;}

Ungolfed & test-code:

Try it here.

import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

class Main{
    static List c(int[] f){
        LinkedList c = new LinkedList();
        for (int i : f){
            c.add(i);
        }
        while(c.size() > 5){
            c.removeLastOccurrence(Collections.min(c));
        }
        return c;
    }

    public static void main(String[] a){
        System.out.println(Arrays.toString(c(new int[]{ 0, 2, 5, 4, 0, 1, 0 }).toArray()));
        System.out.println(Arrays.toString(c(new int[]{ 2, 1, 1, 5, 3, 6 }).toArray()));
        System.out.println(Arrays.toString(c(new int[]{ 0, 4, 5 }).toArray()));
        System.out.println(Arrays.toString(c(new int[]{ 1, 1, 5, 1, 1, 5 }).toArray()));
        System.out.println(Arrays.toString(c(new int[]{ 0, 2, 0, 0, 0, 0, 0, 0 }).toArray()));
        System.out.println(Arrays.toString(c(new int[]{ 0, 0, 0, 0, 1, 0, 0, 0, 0 }).toArray()));
        System.out.println(Arrays.toString(c(new int[]{ 6, 3, 2, 0, 69, 22, 0, 37, 0, 2, 1, 0, 0, 0, 5, 0, 1, 2, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 2 }).toArray()));
    }
}

Output:

[0, 2, 5, 4, 1]
[2, 1, 5, 3, 6]
[0, 4, 5]
[1, 1, 5, 1, 5]
[0, 2, 0, 0, 0]
[0, 0, 0, 0, 1]
[6, 69, 22, 37, 5]

0

Julia, 48 bytes

!x=x[find(sum(x.<x',2)+diag(cumsum(x.==x')).<6)]

Try it online!

How it works

The comment c1 has higher precedence than the comment c2 iff one of the following is true:

  • c1 has more upvotes than c2.
  • c1 and c2 have the same amount of upvotes, but c1 was posted earlier.

This defines a total ordering of the comments, and the task at hand is to find the five comments that have the highest precedences.

Instead of sorting the comments by precedence (which would alter their order, for each comment c, we count the comments that have a greater or equal precedence. We keep c if and only if this count is 5 or less.

To partially sort the comments by number of upvotes, we do the following. Let x be the column vector containing the vote counts. Then x' transposes x ‐ thus creating a row vector ‐ and x.<x' creates a Boolean matrix that compares each element of x with each element of xT.

For x = [0, 2, 5, 4, 0, 1, 0], this gives

<     0      2      5      4      0      1      0
0 false   true   true   true  false   true  false
2 false  false   true   true  false  false  false
5 false  false  false  false  false  false  false
4 false  false   true  false  false  false  false
0 false   true   true   true  false   true  false
1 false   true   true   true  false  false  false
0 false   true   true   true  false   true  false

By summing across rows (via sum(...,2)), we count the number of comments that have strictly more upvotes than the comment at that index.

For the example vector, this gives

4
2
0
1
4
3
4

Next, we count the number of comments with an equal amount of upvotes have been posted earlier than that comment. We achieve this as follows.

First we build an equality table with x.==x', which compraes the elements of x with the elements of xT. For our example vector, this gives:

=     0      2      5      4      0      1      0
0  true  false  false  false   true  false   true
2 false   true  false  false  false  false  false
5 false  false   true  false  false  false  false
4 false  false  false   true  false  false  false
0  true  false  false  false   true  false   true
1 false  false  false  false  false   true  false
0  true  false  false  false   true  false   true

Next, we use cumsum to calculate the cumulative sums of each columns of of the matrix.

1  0  0  0  1  0  1
1  1  0  0  1  0  1
1  1  1  0  1  0  1
1  1  1  1  1  0  1
2  1  1  1  2  0  2
2  1  1  1  2  1  2
3  1  1  1  3  1  3

The diagonal (diag) holds the count of comments that have an equal amount of upvotes and occur no later than the corresponding comment.

1
1
1
1
2
1
3

By adding the two row vectors we produced, we obtain the priorities (1 is the highest) of the comments.

5
3
1
2
6
4
7

Comments with priorities ranging from 1 to 5 should be displayed, so we determine their indices with find(....<6) and retrieve the corresponding comments with x[...].


0

Python 3.5, 68 bytes

f=lambda x,*h:x and x[:sum(t>x[0]for t in x+h)<5]+f(x[1:],*h,x[0]+1)

No match for my Python 2 answer, but only three bytes longer than its port to Python 3, and I think it's different enough to be interesting.

I/O is in form of tuples. Test it on repl.it.

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.