Вид мета: получить самый длинный из самых коротких ответов


14

Ваша задача - если вы ее принимаете - написать программу, которая поможет понять мое предложение по мета-методу путем расчета победителя соревнования . Конечно, ответы на этот вопрос будут рассматриваться как предложенные, поэтому ваша программа (если она правильная) может рассчитать, станет ли ваш ответ принятым.

правила

  • Программа читает файл с несколькими строками следующего формата (см. Пример ниже): [Язык] TAB [NumberOfCharacters] TAB [LinkToAnswer]
  • Имя файла передается в качестве аргумента вашей программе, или файл перенаправляется на стандартный ввод вашей программы. Это ваш выбор, пожалуйста, укажите метод при ответе
  • Ожидается, что формат ввода правильный. Там нет необходимости для обработки ошибок.
  • Количество символов положительное. Ваша программа должна обрабатывать длину до 65535. 64 КБ должно хватить всем :-)
  • Программа выводит те строки на стандартный вывод, которые соответствуют идее метапроекта, то есть
    • выигрывает самый короткий код конкретного языка программирования (фаза сокращения)
    • выигрывает самый длинный код среди всех языков программирования (фаза сортировки)
    • в случае розыгрыша должны быть напечатаны все ответы одинаковой длины
  • Порядок вывода не важен
  • Хотя выигрывает самый длинный код, это не . Ваш код должен быть максимально коротким для вашего языка программирования.
  • Ответы на редко встречающиеся языки программирования, которые не пытаются сократить код, заслуживают отрицательного ответа, потому что они пытаются обойти намерение такого рода вопроса. Если есть только один ответ для конкретного языка программирования, он будет рассматриваться как кандидат-победитель, так что вы можете начать использовать его код.

Пример входного файла (разделенного одиночными вкладками, если возникает проблема с форматированием):

GolfScript  34  http://short.url/answer/ags
GolfScript  42  http://short.url/answer/gsq
C#  210 http://short.url/answer/cs2
Java    208 http://short.url/answer/jav
C#  208 http://short.url/answer/poi
J   23  http://short.url/answer/jsh
Ruby    67  http://short.url/answer/rub
C#  208 http://short.url/answer/yac
GolfScript  210 http://short.url/answer/210

Ожидаемый результат (порядок не важен):

C#  208 http://short.url/answer/poi
C#  208 http://short.url/answer/yac
Java    208 http://short.url/answer/jav

Обновить

Некоторые программы полагаются на тот факт, что существует один максимум (например, символьная программа C # 210). Полученный из реальности, кто-то может также написать программу GolfScript с 210 символами. Выход останется прежним. Я добавил такой GolfScript для ввода.

Обновление 2

Как и предполагалось, я пометил (все еще код-гольф), и крайний срок - 2014-03-06 (что выглядит как произвольная дата, но я вернусь в Германию из поездки тогда).

Окончательные результаты

Я решил проголосовать так:

  • Ответы, в которых количество символов не может быть подтверждено, получают комментарий для объяснения количества.
  • Ответы, которые можно легко уменьшить, получают комментарий, редактируют предложение и переходят к результату с меньшим значением счетчика. (Надеюсь, я видел это заранее).
  • Ответы, которые не компилируются, получают отрицательный ответ. (Как оказалось, довольно сложная задача).
  • Ответы, которые не являются игрой в гольф, получают отрицательную оценку (как уже описано в правилах).
  • Ответы, которые дают ожидаемый результат, получают положительный ответ. Из-за некоторых ответов, которые не работают должным образом, я использую 4 разных входных файла и проверяю ожидаемый результат.

Наконец, победитель определяется путем предоставления таблицы квалификационных ответов в качестве входных данных для моей справочной программы (плюс двойная проверка результата вручную). Если бы мой собственный ответ был победным, я бы исключил его из списка. В случае нескольких победителей я бы выбрал только одного. Поэтому некоторые бонусы можно заработать:

  • ответы, которые принимают больше информации, чем ожидалось (например, за пределами определенных диапазонов)
  • ответы, которые используют умную идею сделать его коротким

Я сделал снимок ответов 6 марта 2014 года, 19:45 UTC + 1. Анализ продолжается. Проверка всех ответов сложнее, чем ожидалось ...


Разве это не должно быть помечено как вызов кода на данный момент? Кроме того, когда срок?
TheConstructor

Ответы:


2

Ява - 556

import java.util.*;class G{public static void main(String[]x){TreeMap<?,TreeMap>m=new TreeMap();try{Scanner s=new Scanner(System.in);for(;;){String[]a=s.nextLine().split("\t");a(new Long(a[1]),a(a[0],m)).put(a[2],a);}}catch(Exception e){}TreeMap<?,Map<?,String[]>>n=new TreeMap();for(TreeMap o:m.values())a(o.firstEntry().getKey(),n).putAll((Map)o.firstEntry().getValue());for(String[]o:n.lastEntry().getValue().values())System.out.println(o[0]+"\t"+o[1]+"\t"+o[2]);}static<T>Map a(T t,Map m){if(m.get(t)==null)m.put(t,new TreeMap());return(Map)m.get(t);}}

Программа будет читать из STDIN.

import java.util.Map;
import java.util.Scanner;
import java.util.TreeMap;

class G {
    public static void main(String[] x) {
        TreeMap<?, TreeMap> m = new TreeMap();
        try {
            Scanner s = new Scanner(System.in);
            for (; ; ) {
                String[] a = s.nextLine().split("\t");
                a(new Long(a[1]), a(a[0], m)).put(a[2], a);
            }
        } catch (Exception e) {
        }
        TreeMap<?, Map<?, String[]>> n = new TreeMap();
        for (TreeMap o : m.values())
            a(o.firstEntry().getKey(), n).putAll((Map) o.firstEntry().getValue());
        for (String[] o : n.lastEntry().getValue().values())
            System.out.println(o[0] + "\t" + o[1] + "\t" + o[2]);
    }

    static <T> Map a(T t, Map m) {
        if (m.get(t) == null)
            m.put(t, new TreeMap());
        return (Map) m.get(t);
    }
}
  1. Программа будет читать построчно, пока не произойдет исключение (либо ArrayIndexOutOfBoundsExceptionкогда встречается пустая строка, либо NoSuchElementExceptionесли ввод заканчивается без завершающей новой строки). Каждая прочитанная строка добавляется к TreeMap m, который мог быть определен какTreeMap<String, TreeMap<Long, TreeMap<String,String[]>>> (слева направо: язык, размер кода, URL, ввод).
  2. Затем создается результат TreeSet<Long, TreeSet<String, String[]>> n(слева направо: размер кода, URL, ввод), в котором firstEntry()агрегируется содержимое всех языков .
  3. lastEntry()из агрегированного TreeMapсодержит наш результат - нам нужно только распечатать его.

Попробуйте на ideone.com (переключил две последние строки ввода, чтобы показать, что все строки прочитаны)


Пришлось добавить переменную для хранения BufferedReader -.-
TheConstructor

1
Может быть, на этот раз победит Java, потому что у нее нет ключевого слова var ...
Томас Уэллер

@ThomasW. только что понял, что оставил некоторые ненужные {} в версии для гольфа -.-
TheConstructor

Также только что рассказал, что я использовал Integer. В то время как int короче, чем long, Integer наверняка стоит сыграть в гольф на Long -.-
TheConstructor

2

Perl, 195 байт

while(<>){/(\S+)\t(\d+)\t(.+)/;push@{$a{$1}},$3if$2==$l{$1};$l{$1}=$2,$a{$1}=[$3]if $2<($l{$1}//65536)}$m=(sort{$b<=>$a}values%l)[0];map{$l=$_;map{print"$l\t$m\t$_\n"if$l{$l}==$m}@{$a{$l}}}keys%l

Ввод ожидается в STDIN, результат записывается в STDOUT:

C#      208     http://short.url/answer/poi
C#      208     http://short.url/answer/yac
Java    208     http://short.url/answer/jav

Неуправляемая версия

#!/usr/bin/env perl
use strict;
$^W=1;

# hash %language remembers the minimum count for a language
# %language: <language> => <minimum count>
my %language;
# hash %array remembers the URLs for the minimum count of the language
# %array: <language> => [<url>, <url>, ....]
my %array;

while(<>){
    # parse input line (no error checking)
    /(\S+)\t(\d+)\t(.+)/;
    my ($lang, $count, $url) = ($1, $2, $3);
    # add URL, if the count is the current minimum for the language
    if ($count == ($language{$lang}//0)) {
    # better, but longer version:
    # if (defined $language{$lang} and $count == $language{$lang}) {
        push @{$array{$lang}}, $url;
    }
    # create a new entry for the language, if there is a new minimum
    if ($count < ($language{$lang}//65536)) {
    # better, but longer version:
    # if (not defined $language{$lang} or $count < $language{$lang}) {
        $language{$lang} = $count;
        $array{$lang} = [$url];   
    }
}

# Sort the minimal values in numerical descending order and
# get the first entry as maximum.
my $maximum = (sort { $b <=> $a } values %language)[0];

# Loop over all URLs of minimal answers for the language,
# but print only the entries for the languages with the largest
# minima.
foreach my $lang (keys %language) {
    foreach my $url (@{$array{$lang}}) {
        if ($language{$lang} == $maximum) {
            print "$lang\t$maximum\t$url\n";
        }
    }
}
__END__

Heiko, как отметил @grovesNL, некоторые программы могут полагаться на тот факт, что существует один максимум. Может быть, вы можете проверить, влияет ли ваша программа. Просто добавьте GolfScript 210 http://short.url/answer/210строку к входу и посмотрите, останется ли вывод таким же. На самом деле, я думаю, что на вас это не влияет, потому что вы используете [0] максимум, но у меня нет Perl, доступного в данный момент, чтобы попробовать.
Томас Уэллер

@ ТомасВ .: Это не влияет. Я добавил строку и вывод остался прежним. После первой части, которая читает файл, структура данных%l / %languageсодержит языки и их минимальные значения. Структура данных %a/ %arrayсодержит только те пары язык / URL, значение которых является минимальным для этого языка. Затем минимальные значения сортируются в порядке убывания, а первое используется как глобальный максимум и как условие фильтра для %a/ %array.
Хайко Обердик,

2

Python 378 377 372

import sys
d=__import__("collections").defaultdict(list)
o={}
x=int
n="\n"
for i,l,u in[a.split()for a in sys.stdin.read().strip().split(n)]:d[i]+=[(l,u)]
for e,b in d.items():o[e]=[i for i in b if i[0]==str(min([x(i[0])for i in b]))]
print("".join(n.join("\t".join([u,s[0],s[1]])for s in y if x(s[0])==max(x(i[0][0])for i in o.values()))+n for u,y in o.items()).strip())

Вход на стандартный ввод:

C:\Users\gcq\Documents\python>type m.txt | python test.py
C#      208     http://short.url/answer/poi
C#      208     http://short.url/answer/yac
Java    208     http://short.url/answer/jav

И это то, что у меня было до того, как я начал сжимать его на 551 символе:

from collections import defaultdict
import sys
d = defaultdict(list)

for language, length, url in [a.split() for a in sys.stdin.read().strip().split("\n")]:
    d[language].append((length, url))

o = {}
for language, data in d.items():
    winval = data[0][0]
    for i in data:
        if int(i[0]) < int(winval):
            winval = i[0]
    o[language] = [i for i in data if i[0] == winval]

maxlen = max(int(i[0][0]) for i in o.values())

for language, dataa in o.items():
    for data in dataa:
        if int(data[0]) == maxlen:
            print("\t".join([language, data[0], data[1]]))

1

C # - 628

Вот более длинная ваша альтернатива, которая использует DataTable:

using Microsoft.VisualBasic.FileIO;namespace System{using T=Data.DataTable;using R=Data.DataRow;using V=Data.DataView;using C=Data.DataColumn;class p{static void Main(string[] a){var I=typeof(Int32);T t=new T();t.Columns.AddRange(new[]{new C("a"),new C("b",I),new C("c"),new C("d",I)});var f=new TextFieldParser(a[0]);f.SetDelimiters("\t");while(!f.EndOfData){var r=t.NewRow();r.ItemArray=f.ReadFields();t.Rows.Add(r);}foreach(R r in t.Rows){r[3]=t.Compute("min(b)","a='"+r[0]+"'");}V v=new V(t);T s=v.ToTable();foreach(R r in s.Select("b='"+t.Compute("max(d)","")+"'")){Console.WriteLine(String.Join("\t",r[0],r[1],r[2]));}}}}

Первоначально я думал, что, возможно, получил небольшое сокращение кода при использовании max / min с DataTable, но типы, необходимые для построенияDataTable (rows / columns / view), к сожалению, добавляют большую длину. Я новичок в коде игры в гольф, так что, возможно, кто-то сможет уменьшить его дальше. Все еще веселый вызов.


1

дг - 286 281 260 251 218 байт

import '/sys'
d=dict!
for(a,b,c)in(map str.split$(sys.stdin.read!).splitlines!)=>d!!a=(d.get a list!)+(list'(int b,c))
for(i,l)in(d.items!)=>for(s,u)in l=>s==(max$map(i->fst$min i)d.values!)=>print$i+' '+(str s)+' '+u

Пример:

$ cat langs.txt | dg langs.dg 
C# 208 http://short.url/answer/poi
C# 208 http://short.url/answer/yac
Java 208 http://short.url/answer/jav

Безголовая версия:

import '/sys'

s = sys.stdin.read!
d = dict!
# convert the string into a list of tuples (name, score, url)
u = map str.split $ s.splitlines!
# add all the values to the dict (converting the score to an integer)
for (a, b, c) in u =>
  d!!a = (d.get a list!) + (list' (int b, c))
# computes the maximum value amongst the mins
m = max $ map (i -> fst $ min i) d.values!
for (i, l) in (d.items!) =>
  for (s, u) in l =>
    # if the score equals the maximum then print all the line
    s == m => print $ i + ' ' + (str s) + ' ' + u  # actually here .format()
                                                   # would be better

Q: Какого черта dg?
A: Язык программирования, который компилируется в байт-код CPython, так же, как Scala компилируется в JVM. По сути это означает, что dg является альтернативным синтаксисом для Python 3. Он также позволяет использовать все существующие библиотеки.

Больше информации здесь (даже учебник!): Https://pyos.github.io/dg


Если я помещу это в файл, он будет иметь только 217 байтов (окончание строки в Linux)
Томас Веллер

@ThomasW. Weird! С помощью cat langs.dg | wc -cя получаю 218!
Рубик

Может быть, завершающий символ новой строки или нет завершающего символа новой строки?
TheConstructor

@TheConstructor это могло бы быть, хотя это не должно сохранять это с новой строкой oO
rubik

1

Реболь - 314

d: map[]foreach r read/lines to-file system/script/args[r: split r tab p: take r r/1: to-integer r/1 r/2: reduce[r/2]either none? d/:p[repend d[p r]][case[d/:p/1 > r/1[d/:p: r]d/:p/1 = r/1[append d/:p/2 r/2]]]]l: 0 foreach[k v]d[l: max l v/1]foreach[k v]d[if l = v/1[foreach n v/2[print rejoin[k tab v/1 tab n]]]]

ун-golfed

d: map []

foreach r read/lines to-file system/script/args [
    r: split r tab
    p: take r
    r/1: to-integer r/1
    r/2: reduce [r/2]
    either none? d/:p [repend d [p r]] [
        case [
            d/:p/1 > r/1 [d/:p: r]
            d/:p/1 = r/1 [append d/:p/2 r/2]
        ]
    ]
]

l: 0 foreach [k v] d [l: max l v/1]
foreach [k v] d [
    if l = v/1 [
        foreach n v/2 [print rejoin [k tab v/1 tab n]]
    ]
]

Пример использования:

$ rebol script.reb data.txt
C#    208   http://short.url/answer/poi
C#    208   http://short.url/answer/yac
Java  208   http://short.url/answer/jav

0

C # - 515

Ожидает имя файла в качестве аргумента

using System.Collections.Generic;namespace N{using S=SortedList<int,T>;class T:List<string>{static void Main(string[]a){var d=new Dictionary<string,S>();int n,m=0;T w=new T();foreach(var l in System.IO.File.ReadAllLines(a[0])){var p=(a=l.Split('\t'))[0];n=int.Parse(a[1]);if(!d.ContainsKey(p))d.Add(p,new S());if(!d[p].ContainsKey(n))d[p].Add(n,new T());d[p][n].Add(l);}foreach(var e in d){n=e.Value.Keys[0];if(n==m)w.AddRange(e.Value[n]);if(n>m)w=e.Value[m=n];}foreach(var e in w)System.Console.WriteLine(e);}}}

Сначала я разработал свою C # -программу, чтобы быть прямой, потому что я хотел иметь своего рода справочную программу. Но потом я решил сам участвовать в конкурсе и сыграть в гольф. Это одна из более ранних версий кода + некоторые комментарии:

// N: namespace
// P: Program
// S: type definition: sorted dictionary
// a: arguments
// d: data container
// r: lines read from text file
// l: single line from r
// t: tabbed part of l after splitting
// p: programming language name
// n: character count
// m: maximum character count
// w: list of winners
// e: entry in data container
// c: winner candidate
using System.Collections.Generic;
namespace N
{
    using S = SortedList<int, P>;
    public class P : List<string>
    {
        public static void Main(string[] a)
        {
            var r = System.IO.File.ReadAllLines(a[0]);
            // Make it a data structure
            var d = new Dictionary<string, S>();
            foreach (var l in r)
            {
                var t = l.Split('\t');
                var p = t[0];
                var n = int.Parse(t[1]);
                if (!d.ContainsKey(p)) d.Add(p, new S());
                if (!d[p].ContainsKey(n)) d[p].Add(n, new P());
                d[p][n].Add(l);
            }
            // Get the maximum values
            var m = 0;
            P w = null;
            foreach (var e in d)
            {
                foreach (var s in e.Value.Keys)
                {
                    if (s > m)
                    {
                        w = e.Value[s];
                        m = s;
                    }
                    else if (s == m)
                    {
                        w.AddRange(e.Value[s]);
                    }
                    break; // Break here to get the shortest solution per language
                }
            }
            // Print everything on console
            foreach (var e in w)
            {
                System.Console.WriteLine(e);
            }
        }
    }
}

Кажется, 515 размер файла на моем диске включает в себя метку порядка байтов. Копирование / вставка отсюда занимает всего 512 байт.
Томас Уэллер,

0

C # - 460 359

Поняв, насколько громоздким было мое DataTableрешение, я создал следующий пример с использованием Linq. Он использует ту же методологию, что и мое предыдущее решение.

Golfed

namespace System{using Linq;using IO;class p{static void Main(string[]i){var l=(from f in File.ReadAllLines(i[0])let s=f.Split('\t')select new Tuple<string,int,string>(s[0],Convert.ToInt16(s[1]),f)).ToList();foreach(var f in l.Where(a=>a.Item2==l.Where(b=>b.Item1==l.Single(c=>c.Item2==l.Max(d=>d.Item2)).Item1).Min(e=>e.Item2)))Console.WriteLine(f.Item3);}}}

Ungolfed

namespace System
{
    using Linq;
    using IO;
    class p
    {
        static void Main(string[]i)
        {
            var l=(from f in File.ReadAllLines(i[0])
                   let s=f.Split('\t')
                   select new Tuple<string, int, string>(s[0],Convert.ToInt16(s[1]),f)).ToList();
            foreach(var f in l.
                Where(a=>a.Item2==l.
                    Where(b=>b.Item1==l.
                        Single(c=>c.Item2==l.
                            Max(d=>d.Item2)).Item1).
                                Min(e=>e.Item2)))
            Console.WriteLine(f.Item3);
        }
    }
}

Я все еще довольно новичок в Linq, поэтому я почти уверен, что эти выражения могут быть сокращены дальше.

Из вашего вопроса не ясно, существует ли единственное решение максимальной длины. В своих ответах я использовал предположение о том, что существует одна максимальная точка (т. Е. Если был также максимум в GolfScript, равный 210, он может потерпеть неудачу в зависимости от возвращенной записи «Максимальный максимум»). Решение Хейко будет иметь ту же проблему. Чтобы исправить это, мы должны были бы добавить еще один шаг, который содержал список связанных максимумов, чтобы проверить минимумы для каждого языка.


1
Мне кажется, что вы можете сохранить f как Item3 (вместо s [2]), а затем записать f.Item3 на консоль без необходимости рекомбинации Item1 и Item2.
Томас Веллер

Спасибо за разъяснение требований. Исходя из реальности, я бы сказал, что может случиться так, что кто-то (очевидно, неопытный) напишет GolfScript с 210 символами.
Томас Веллер

1
Если вы преобразуете первый цикл foreach в LINQ, он становится еще короче:namespace System{using Linq;using IO;class p{static void Main(string[]i){var l=(from f in File.ReadAllLines(i[0])let s=f.Split('\t') select new Tuple<string, int, string>(s[0],Convert.ToInt16(s[1]),f)).ToList();foreach(var f in l.Where(a=>a.Item2==l.Where(b=>b.Item1==l.Single(c=>c.Item2==l.Max(d=>d.Item2)).Item1).Min(e=>e.Item2)))Console.WriteLine(f.Item3);}}}
Томас Веллер

@ThomasW .: Хорошая идея для раскола. Спасибо за преобразование цикла foreach, я думал об этом, добавляя это первоначально, но я не знал, что смогу использовать так.
grovesNL

Я думаю , что я начинаю понимать , что ваш запрос делает :) , и это также не будет для упрощения ввода , как это: Golfscript 100 ..., C# 1 ..., C# 200 .... Это, вероятно, нуждается в доработке
Томас Уэллер

0

С ++ - 535

Выводятся только ответы, связанные с самой длинной позицией, после выбора только самых коротких ответов каждого языка в качестве потенциальных победителей.

#include<fstream>
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main(){

    string s;
    vector<string>l;
    vector<int>v;
    vector<string>u;
    cin>>s;

    ifstream i(s.c_str());

    do{
        int n;
        i>>s;
        if(i.eof())break;
        l.push_back(s);
        i>>n;
        v.push_back(n);
        i>>s;
        u.push_back(s);
    }while(1);

    for(int i=0;i<l.size();i++){
        for(int j=0;j<l.size();j++){
            if(l[j]==l[i]){
                if(v[i]>v[j])l[i]="";
                else if(v[i]<v[j])l[j]="";
            }
        }
    }
    int n=0;
    for(int i=0;i<v.size();i++)
        if(n<v[i]&l[i]!="")n=v[i];

    for(int i=0;i<v.size();i++)
        if(v[i]==n)cout<<l[i]<<'\t'<<v[i]<<'\t'<<u[i]<<endl;
}

Гольф (не такой нечитаемый, как некоторые языки):

#include<fstream>
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main(){string s;vector<string>l;vector<int>v;vector<string>u;cin>>s;ifstream i(s.c_str());do{int n;i>>s;if(i.eof())break;l.push_back(s);i>>n;v.push_back(n);i>>s;u.push_back(s);}while(1);for(int i=0;i<l.size();i++)for(int j=0;j<l.size();j++)if(l[j]==l[i]){if(v[i]>v[j])l[i]="";else if(v[i]<v[j])l[j]="";}int n=0;for(int i=0;i<v.size();i++)if(n<v[i]&l[i]!="")n=v[i];for(int i=0;i<v.size();i++)if(v[i]==n)cout<<l[i]<<'\t'<<v[i]<<'\t'<<u[i]<<endl;}

Вы проверили свои результаты по сравнению с ожидаемым результатом? С 8 строками ввода он должен выдавать только 3 строки. Кажется, ваша программа выводит все.
Томас Уэллер

@ThomasW. О, я неправильно понял эту часть. Я удалю это сейчас.

@ThomasW. Это выглядит правильно?

Если я помещу это в файл, я получу 540 байт, а не 535. Не могли бы вы дважды проверить длину, пожалуйста?
Томас Веллер,

Это 535 символов. Мы оба правы. Я могу изменить это, если хочешь.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.