Tipo de meta: obtenha a mais longa das respostas mais curtas

14

Sua tarefa - se você a aceitar - é escrever um programa que ajude a entender minha proposta no meta , calculando o vencedor de uma competição . Obviamente, as respostas a essa pergunta serão tratadas como propostas, para que seu programa (se correto) possa calcular se sua resposta se tornará a resposta aceita.

Regras

  • O programa lê um arquivo com várias linhas do seguinte formato (veja o exemplo abaixo): TAB [Language] [TAB] [NumberOfCharacters] TAB [LinkToAnswer]
  • O nome do arquivo é passado como argumento para o seu programa ou o arquivo é redirecionado para a entrada padrão do seu programa. A escolha é sua, por favor mencione o método ao dar a resposta
  • É esperado que o formato de entrada esteja correto. Não há necessidade de tratamento de erros.
  • O número de caracteres é positivo. Seu programa deve lidar com comprimentos de até 65535. 64k deve ser suficiente para todos :-)
  • O programa gera as linhas na saída padrão que atendem à idéia da meta proposta, ou seja,
    • o código mais curto de uma linguagem de programação específica vence (fase de redução)
    • o código mais longo de todas as linguagens de programação vence (fase de classificação)
    • em caso de empate, todas as respostas com o mesmo comprimento devem ser impressas
  • A ordem da saída não é importante
  • Embora o código mais longo ganhe, esse não é o . Seu código deve ser o mais curto possível para sua linguagem de programação.
  • As respostas sobre raramente as linguagens de programação que não estão tentando reduzir o código merecem um voto negativo, porque tentam ignorar a intenção desse tipo de pergunta. Se houver apenas uma resposta para uma linguagem de programação específica, ela será considerada uma candidata vencedora, para que você possa começar a soprar seu código.

Arquivo de entrada de exemplo (separado por guias únicas, se houver um problema com a formatação):

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

Saída esperada (a ordem não é importante):

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

Atualizar

Alguns programas se baseiam no fato de que há um único máximo (como o programa de caracteres C # 210). Derivado da realidade, alguém também pode escrever um programa GolfScript com 210 caracteres. A saída permaneceria a mesma. Eu adicionei um GolfScript à entrada.

Atualização 2

Como sugerido, retirei novamente (ainda código-golfe também) e o prazo é 06/03/2014 (que parece uma data arbitrária, mas voltarei para a Alemanha depois de viajar).

Resultados finais

Decidi votar da seguinte forma:

  • As respostas em que o número de caracteres não pode ser confirmado recebem um comentário para explicar a contagem.
  • As respostas que podem ser facilmente reduzidas recebem um comentário, uma sugestão de edição e entram no resultado com o menor valor de contagem. (Espero ter visto isso com antecedência).
  • Respostas que não são compiladas recebem um voto negativo. (Bastante uma tarefa difícil, como se vê).
  • As respostas que não são jogadas no golfe recebem um voto negativo (conforme descrito nas regras já).
  • As respostas que produzem o resultado esperado recebem um voto positivo. Devido a algumas respostas que não funcionam conforme o esperado, eu uso 4 arquivos de entrada diferentes e verifico o resultado esperado.

Finalmente, o vencedor é determinado fornecendo a tabela de respostas qualificadas como entrada para o meu programa de referência (além de verificar o resultado manualmente). Se minha resposta fosse a vencedora, eu a excluiria da lista. No caso de vários vencedores, eu teria que escolher apenas um. Portanto, alguns bônus podem ser ganhos:

  • respostas que aceitam mais informações do que o esperado (por exemplo, fora dos intervalos definidos)
  • respostas que usam uma idéia inteligente de torná-lo curto

Tirei um instantâneo das respostas em 6 de março de 2014, 19:45 UTC + 1. A análise está em andamento. Verificar todas as respostas é mais difícil do que o esperado ...

Thomas Weller
fonte
Isso não deve ser marcado como desafio de código por enquanto? Além disso, quando é o prazo?
TheConstructor
2
Alt-nome para isso é Code-Blackjack
VoronoiPotato

Respostas:

2

Java - 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);}}

O programa lerá em 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. O programa lerá linha por linha até que ocorra uma exceção ( ArrayIndexOutOfBoundsExceptionquando uma linha em branco for encontrada ou NoSuchElementExceptionse a entrada terminar sem seguir uma nova linha). Cada linha lida é adicionada ao TreeMap m, que poderia ter sido definida como TreeMap<String, TreeMap<Long, TreeMap<String,String[]>>>(da esquerda para a direita: idioma, tamanho do código, URL, entrada).
  2. Em seguida, um resultado TreeSet<Long, TreeSet<String, String[]>> n(da esquerda para a direita: tamanho do código, URL, entrada) é construído onde o conteúdo de todos os idiomas firstEntry()é agregado.
  3. lastEntry()do agregado TreeMapcontém nosso resultado - precisamos apenas imprimi-lo.

Experimente em ideone.com (as duas últimas linhas de entrada alteradas para mostrar que todas as linhas são lidas)

TheConstructor
fonte
Tinha que adicionar uma variável para armazenar o BufferedReader -.-
TheConstructor
1
Talvez Java ganha desta vez, porque ele não tem uma palavra-chave var ...
Thomas Weller
@ThomasW. só percebi Deixei um pouco desnecessário {} dentro da versão golfed -.-
TheConstructor
Também relaized eu estava usando inteiro. Enquanto int for menor que o longo, o número inteiro deve ser tachado para Long -.-
TheConstructor
2

Perl, 195 bytes

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

A entrada é esperada em STDIN, o resultado é gravado em STDOUT:

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

Versão ungolfed

#!/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 Oberdiek
fonte
Heiko, como o @grovesNL apontou, alguns programas podem se basear no fato de que existe um único máximo. Talvez você possa verificar se o seu programa é afetado. Basta adicionar uma GolfScript 210 http://short.url/answer/210linha à entrada e ver se a saída permanece a mesma. Na verdade, acho que o seu não é afetado, porque você está usando [0] para o máximo, mas não tenho o Perl disponível no momento para tentar.
Thomas Weller
@ ThomasW .: Não é afetado. Eu adicionei a linha e a saída permanece a mesma. Após a primeira parte que lê o arquivo, a estrutura de dados %l/ %languagecontém os idiomas e seus valores mínimos. A estrutura de dados %a/ %arraycontém apenas os pares de idioma / URL, cujo valor é o mínimo para esse idioma. Em seguida, os valores mínimos são classificados em ordem decrescente e o primeiro é usado como máximo global e como condição de filtro para %a/ %array.
Heiko Oberdiek
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())

Entrada no stdin:

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

E é isso que eu tinha antes de começar a compactá-lo, em 551 caracteres:

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]]))
gcq
fonte
1

C # - 628

Aqui está uma alternativa mais longa que usa 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]));}}}}

Originalmente, pensei que poderia ter conseguido uma leve redução de código usando max / min com DataTable, mas os tipos necessários para criar o DataTable(linhas / colunas / exibição) adicionam muito comprimento, infelizmente. Eu sou novo em codificar golfe, então talvez alguém possa reduzi-lo ainda mais. Ainda é um desafio divertido.

grovesNL
fonte
1

dg - 286 281 260 251 218 bytes

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

Exemplo:

$ 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

Versão não destruída :

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: O que diabos é dg?
R: Uma linguagem de programação que é compilada no bytecode do CPython, assim como o Scala é compilado nas JVMs. Isso significa essencialmente que o dg é uma sintaxe alternativa para o Python 3. Ele permite que você use todas as bibliotecas existentes também.

Mais informações aqui (mesmo um tutorial!): Https://pyos.github.io/dg

rubik
fonte
Se eu colocar isso em um arquivo, ele tem apenas 217 bytes (final de linha Linux)
Thomas Weller
@ThomasW. Esquisito! Usando cat langs.dg | wc -ceu recebo 218!
Rubik
Talvez a nova linha final vs. a nova linha final?
TheConstructor
@TheConstructor poderia ser, embora não deve salvá-lo com um oO nova linha
Rubik
1

Rebol - 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]]]]

sem golfe

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]]
    ]
]

Exemplo de uso:

$ 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
draegtun
fonte
0

C # - 515

Espera um nome de arquivo como argumento

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);}}}

Primeiro, eu projetei meu programa C # para ser direto, porque queria ter um tipo de programa de referência. Mas então eu decidi também entrar em uma competição e jogar golfe. Esta é uma das versões anteriores do código + alguns comentários:

// 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);
            }
        }
    }
}
Thomas Weller
fonte
Parece que o tamanho do arquivo 515 no meu disco incluiu uma marca de ordem de bytes. Copiar / colar a partir daqui é apenas 512 bytes.
22416 Thomas Weller #
0

C # - 460 359

Depois de perceber o quão volumoso meu DataTable era solução, criei o seguinte exemplo usando o Linq. Ele usa a mesma metodologia da minha solução anterior.

Golfe

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);
        }
    }
}

Eu ainda sou bastante novo no Linq, então tenho quase certeza de que essas expressões podem ser reduzidas ainda mais.

Na sua pergunta, não está claro se existe uma única solução de comprimento máximo. Para minhas respostas, usei a suposição de que existe um único ponto máximo (por exemplo, se também houver um máximo de 210 no GolfScript, ele poderá falhar com base no registro máximo único retornado). A solução da Heiko teria o mesmo problema. Para corrigir isso, teríamos de adicionar outra etapa que continha uma lista de máximos vinculados para verificar os mínimos para cada idioma.

grovesNL
fonte
1
Parece-me que você pode salvar f como Item3 (em vez de s [2]) e depois gravar f.Item3 no console sem a necessidade de recombinar o Item1 e o Item2.
Thomas Weller
Obrigado pelo esclarecimento dos requisitos. Derivado da realidade, eu diria que poderia acontecer que alguém (inexperiente, obviamente) escrevesse um GolfScript com 210 caracteres.
Thomas Weller
1
Se você converter o primeiro loop foreach em LINQ, ele se tornará ainda mais curto: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);}}}
Thomas Weller
@ ThomasW .: Boa ideia para a divisão. Obrigado pela conversão do loop foreach, pensei em adicionar isso originalmente, mas não sabia que poderia usar dessa maneira.
grovesNL
Eu acho que começamos a compreender o que sua consulta não :) e também falhará para a entrada mais simples como isto: Golfscript 100 ..., C# 1 ..., C# 200 .... Isso provavelmente precisa de algum retrabalho
Thomas Weller
0

C ++ - 535

Somente produzirá as respostas empatadas para a posição mais longa depois de selecionar apenas as respostas mais curtas de cada idioma como possíveis vencedores.

#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;
}

Golfe (não tão ilegível quanto alguns idiomas):

#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;}

fonte
Você verificou sua saída em relação à saída esperada? Com 8 linhas de entrada, deve fornecer apenas 3 linhas como saída. Seu programa parece produzir tudo.
Thomas Weller
@ThomasW. Oh, eu não entendi essa parte. Vou removê-lo por enquanto.
@ThomasW. Isso parece certo?
Se eu colocar isso em um arquivo, recebo 540 bytes, e não 535. Você pode verificar o comprimento, por favor?
21416 Thomas Weller #
São 535 caracteres. Nós dois estamos corretos. Eu posso mudar se você quiser.