Minha palavra pode bater sua palavra

26

PROBLEMA

Dadas duas palavras, encontre o vencedor em uma batalha raiz digital .

Defina a raiz digital de uma palavra da seguinte maneira:

  1. A cada letra do alfabeto é atribuído um número: A = 1, B = 2, C = 3, ..., Z = 26
  2. Adicione os valores para cada letra para totalizar a palavra. Veja "CAT", por exemplo. C + A + T = 3 + 1 + 20 = 24
  3. Adicione todos os dígitos que compõem esse resultado: 24 => 2 + 4 = 6
  4. Repita a etapa 3 até atingir um único dígito. Esse dígito único é a raiz digital da palavra.

Regras:

  1. Um vencedor é declarado se sua raiz digital for maior que a outra.
  2. Se os valores da raiz digital forem iguais, reduza as palavras removendo todas as instâncias da letra de valor mais alto das palavras e recalculando.
  3. Repita as etapas 1 e 2 até que haja um vencedor ou uma das palavras tenha apenas uma única letra (ou nenhuma letra) restante.
  4. Se os valores da raiz digital forem iguais após o processo de redução, a palavra mais longa será declarada vencedora.
  5. Se as palavras tiverem o mesmo comprimento e nenhum vencedor for encontrado após o processo de redução, nenhum vencedor será declarado.

Regras especiais:

  1. Não é permitido o uso de módulo no cálculo da própria raiz digital . Pode ser usado em qualquer outro lugar.
  2. Suponha que as palavras consistam apenas em letras maiúsculas - sem pontuação, sem espaços, etc.

ENTRADA

Puxe as palavras por stdin (separadas por vírgula). parâmetros do método, ou como você desejar. Deixe claro em sua solução ou no código como as palavras são analisadas ou preparadas.

SAÍDA

Mostre a palavra vencedora. Se não houver vencedor, exiba "STALEMATE".

Exemplos:

intput: CAN, BAT

CAN = 18 = 9
BAT = 23 = 5 

saída: CAN

intput: ZOO, NÃO

ZOO = 56 = 11 = 2
NO = 29 = 11 = 2

OO = 30 = 3
N = 14 = 5

saída: NÃO

UPDATE : A entrada deve ser lida usando stdin com as palavras como uma sequência separada por vírgula.

UPDATE : Adicionados alguns exemplos para testar.

ATUALIZAÇÃO : esclareceu a remoção da letra mais valorizada em caso de empate - isso também altera levemente a condição de parada - se uma palavra tiver uma letra ou zero letras, o processo de encurtamento será interrompido

Steve
fonte
Você deve decidir sobre a entrada, não deixá-la para a escolha, pois isso faz uma enorme diferença nos programas. Ao escolher um método de entrada e especificá-lo, você remove "interpretações criativas" e faz um desafio que é igual para todos.
MtnViewMark
@MtnViewMark - Entendido, mas efetivamente estou tentando remover a leitura da entrada da contagem de caracteres. Não estou interessado na maneira mais inteligente ou curta de ler as duas palavras. Exigir um método específico também prejudica certas linguagens - acho que estou apenas tentando entender o problema do problema.
Steve
1
@ Steve - Então você não deve especificar a saída como "display", sim? No entanto, acho que você talvez esteja eliminando muito do problema. Um golfe inteligente e curto geralmente resulta da combinação de diferentes aspectos do problema de maneiras complicadas, por exemplo, dobrando parte do processamento na entrada ou na saída. Quanto aos idiomas para deficientes - praticamente todos eles podem ler stdin e escrever stdout.
MtnViewMark 22/02
@MtnViewMark - Fair point. Vou fazer uma atualização simples e esclarecê-la. Minha linguagem de escolha apenas tem uma maneira longa de ler stdin, então eu sou tendenciosa. :)
Steve
Tomando a entrada um argumento para main conta como sendo de stdin? Ah, e geralmente, se você quiser manter os requisitos baixos em coisas perdidas, como ler no stdin e precisar importar ou incluir outros módulos ou arquivos, fazer com que o quebra-cabeça exija uma função, em vez de um programa inteiro provavelmente ser o melhor caminho a percorrer .
Jonathan M Davis

Respostas:

9

J, 100

z=:"."0@":@(+/)^:9@(64-~a.i.])@(#~' '&i.)"1
f=:*@-/"2@(z@((]#~]i.~{.@\:~)"1^:([:=/z))){'STALEMATE'&,

corre assim:

f 'NO',:'ZOO'
NO       
f 'CAN',:'BAT'
CAN      
f 'FAT',:'BANANA'
FAT      
f 'ONE',:'ONE'
STALEMATE

ele não ainda aceitar a entrada exatamente como solicitado.

Eelvex
fonte
9

APL (Dyalog) ( 91 86)

⎕ML←3⋄{Z≡∪Z←{2>⍴⍕⍵:⍵⋄∇+/⍎¨⍕⍵}¨+/¨⎕A∘⍳¨⍵:G[↑⍒Z]⋄1∊↑¨⍴¨⍵:'STALEMATE'⋄∇1∘↓¨⍵}G←Z⊂⍨','≠Z←⍞

Explicação (em ordem de execução):

  • ⎕ML←3: defina ML como 3 (isso significa partição média, entre outras coisas).
  • G←Z⊂⍨','≠Z←⍞: lê a entrada, separa por vírgulas, armazena em G e passa para a função.
  • +/¨⎕A∘⍳¨⍵: calcule a pontuação de cada palavra. ( ⎕Aé uma lista que contém o alfabeto.)
  • Z←{2>⍴⍕⍵:⍵⋄∇+/⍎¨⍕⍵}¨: calcule a raiz digital para cada pontuação (somando todos os dígitos, enquanto houver mais de um dígito) e armazene-os em Z.
  • Z≡∪Z: se todas as pontuações forem únicas ...
  • :G[↑⍒Z]: ... em seguida, imprima a palavra com a pontuação mais alta (da lista original).
  • ⋄1∊↑¨⍴¨⍵:'STALEMATE': caso contrário (se houver um empate), se uma das palavras tiver comprimento 1, produza STALEMATE.
  • ⋄∇1∘↓¨⍵: caso contrário, retire a primeira letra de cada palavra e execute a função novamente.
marinus
fonte
5

Ruby - 210

d,e=(a,b=$<.read.chop.split(/,/)).map{|w|w.bytes.sort}
r=->w,o=65{n=0;w.map{|c|n+=c-o};n>9?r[n.to_s.bytes,48]:n}
d.pop&e.pop while r[d]==r[e]&&d[1]&&e[1]
$><<[[:STALEMATE,a,b][a.size<=>b.size],a,b][r[d]<=>r[e]]

Testes:

$ ruby1.9 1128.rb <<< CAN,BAT
CAN

$ ruby1.9 1128.rb <<< ZOO,NO
NO

$ ruby1.9 1128.rb <<< ZOO,ZOO
STALEMATE
Arnaud Le Blanc
fonte
A primeira linha pode ser reduzida para d,e=(a,b=gets.split ?,).map{|w|w.bytes.sort}.
Ventero 23/02
Por que não reduzi-lo ainda mais usando alguma outra palavra para indicar um empate? ie "TIE" vs. "STALEMATE"
Gaffi
@ Gaaffi, porque a especificação exige que a palavra "STALEMATE" seja usada.
Paul Prestidge
@chron Shame on me, eu parei de ler no"If the words are of equal length and no winner is found after going through the shortening process, no winner is declared."
Gaffi
5

Haskell, 205 caracteres

import List
s b=d.sum.map((-b+).fromEnum)
d q|q<10=q|1<3=s 48$show q
f=map(s 64.concat).tails.group.reverse.sort
w(a,_:b)=f a#f b where x#y|x<y=b|x>y=a|1<3="STALEMATE"
main=getLine>>=putStrLn.w.span(/=',')

Amostras de execuções:

> ghc --make WordVsWord.hs 
[1 of 1] Compiling Main             ( WordVsWord.hs, WordVsWord.o )
Linking WordVsWord ...

> ./WordVsWord <<< CAN,BAT
CAN

> ./WordVsWord <<< ZOO,NO
NO

> ./WordVsWord <<< FAT,BANANA
FAT

> ./WordVsWord <<< ONE,ONE
STALEMATE

  • Edit: (227 -> 219) melhor escolha do vencedor, correspondência de padrão reduzida w, módulo mais antigo e mais curto importado
  • Edit: (219 -> 208) Incorpore as sugestões de JB
  • Edit: (208 -> 205) manipula números negativos, explorando regras ímpares em Haskell sobre hífen
MtnViewMark
fonte
1
Usar a comparação direta é um toque muito agradável. Algumas melhorias sugeridas "de relance": ',':b_:b(-2), se você não estiver muito apegado ao processamento de interact$unlines.map([...]).linesvárias putStr.[...]=<<getLinelinhas → (-11), se você se permitir diminuir a saída putStrprint(-1). Eu odeio essas operações de negação usando tantos caracteres, mas não consigo encontrar uma maneira de contornar isso.
JB
Obrigado, JB! Eu incorporei a maioria das sugestões. Eu senti que a saída deveria seguir as especificações, em particular terminar com uma nova linha. Mas eu estaria disposto a salvar esses dois personagens se chegasse perto! :-)
MtnViewMark 24/02
Bom trabalho com as subtrações!
JB
3

Perl, 224 225 229

Golfe básico (nada inteligente ainda):

split",",<>;$_=[sort map-64+ord,/./g]for@a=@_;{for(@b=@a
){while($#$_){$s=0;$s+=$_ for@$_;$_=[$s=~/./g]}}($a,$b)=
map$$_[0],@b;if($a==$b){pop@$_ for@a;@{$a[1]}*@{$a[0]}&&
redo}}say+("STALEMATE",@_)[$a<=>$b||@{$a[0]}<=>@{$a[1]}]

Perl 5.10 e superior, execute com perl -M5.010 <file>ouperl -E '<code here>'

$ perl -M5.010 word.pl <<<CAN,BAT
CAN
$ perl -M5.010 word.pl <<<ZOO,NO
NO

$ perl -M5.010 word.pl <<<NO,ON
STALEMATE
JB
fonte
2

K, 106

{a::x;@[{$[(>). m:{+/"I"$'$+/@[;x].Q.A!1+!26}'x;a 0;(<). m;a 1;.z.s 1_'x@'>:'x]};x;"STALEMATE"]}[","\:0:0]

Usa o tratamento de exceções para detectar erros de pilha, que resultam em casos de impasse.

tmartin
fonte
2

VBA ( 242 462)

Function s(q,Optional l=0)
s=-1:t=Split(q,","):r=t:m=t
For j=0 To 1
m(j)=0:w=t(j)
While Len(w)>1 Or Not IsNumeric(w)
b=0
For i=1 To Len(w)
a=Mid(w,i,1):a=IIf(IsNumeric(a),a,Asc(a)-64):b=b+a
If m(j)+0<a+0 Then m(j)=a
Next
w=b
Wend
r(j)=b
Next
s=IIf(r(0)>r(1),0,IIf(r(0)<r(1),1,s))
For j=0 To 1
r(j)=Replace(t(j),Chr(m(j)+64),"",,1)
Next
If s<0 And Len(t(0))+Len(t(1))>2 Then s=s(r(0) & "," & r(1),1)
If l=0 Then If s>=0 Then s=t(s) Else s="STALEMATE"
End Function

Acontece que o código abaixo não corresponde à especificação, então tive que refazer o trabalho, adicionando muito comprimento (veja acima). : - / Talvez seja possível jogar mais golfe, mas já é bastante compacto e duvido que seja capaz de trazê-lo de volta a uma pontuação competitiva.

O original (abaixo) não removeu a letra de maior valor das palavras quando houve um empate.

Sub s(q)
t=Split(q,",")
r=t
For j=0 To 1
w=t(j):b=0
For i=1 To Len(w)
b=b+Asc(Mid(w,i,1))-64
Next
While Len(b)>1
d=0
For i=1 To Len(b)
d=d+Mid(b,i,1)
Next
b=d
Wend
r(j)=b
Next
MsgBox IIf(r(0)>r(1),t(0),IIf(r(0)<r(1),t(1),"STALEMATE"))
End Sub
Gaffi
fonte
2

Isso realmente me agradou e é o meu primeiro post. Embora seja antigo, notei que ninguém havia feito uma versão php, então aqui está a minha.

<?php $f='CAN,CBN';$w=explode(',',$f);$a=$ao=$w[0];$b=$bo=$w[1];$c='';
function splice($a,$t){$s=$h=0;$y=array();$x=str_split($a);
foreach($x as $k=>$v){$s=$s+ord($v)-64;if($v>$h){$h=$k;}}
$y[0]=$s;if($t==1){unset($x[$h1]);$y[1]=$x;}return $y;}
while($c==''){$y1=splice($a,0);$y2=splice($b,0);$y3=splice($y1[0],1);
$y4=splice($y2[0],1);if($y3[0]>$y4[0]){$c=$ao;}else if($y3[0]<$y4[0]){$c=$bo;
}else if((strlen($a)<1)OR(strlen($b)<1)){if(strlen($a)<strlen($b)){$c=$ao;}
else if(strlen($b)<strlen($a)){$c=$bo;}else{$c='STALEMATE';}}}
echo $c;
?>

534 caracteres.

Agora não tenho certeza das regras para começar, então comecei com $ f = 'CAN, CBN' como minha entrada. Espero que esteja certo. Eu executei todos os testes e ele passou em todos eles, embora não seja particularmente elegante. Eu realmente preciso dormir um pouco agora, mas me diverti muito trabalhando nisso - obrigado por um ótimo quebra-cabeça.

Codificado em http://codepad.org/ZSDuCdin

Paul Drewett
fonte
Você pode usar $f=trim(fgets(fopen('php://stdin')));para tirar a entrada.
Elektra
Risque isso, $w=fgetcsv(STDIN);funciona melhor.
Elektra
1

D: 326 caracteres

import std.algorithm,std.array,std.conv,std.stdio;void main(string[]a){alias reduce r;auto b=array(splitter(a[1],","));auto s=map!((a){int n=r!"a+b"(map!"cast(int)(a-'A')+1"(a));while(n>9)n=r!"a+b"(map!"cast(int)(a-'0')"(to!string(n)));return n;})(b);int v=r!"a>b?a:b"(s);writeln(count(s,v)>1?"STALEMATE":b[countUntil(s,v)]);}

Mais legivelmente:

import std.algorithm, std.array, std.conv, std.stdio;

void main(string[] a)
{
    alias reduce r;

    auto b = array(splitter(a[1], ","));
    auto s = map!((a){int n = r!"a + b"(map!"cast(int)(a - 'A') + 1"(a));

                      while(n > 9)
                          n = r!"a+b"(map!"cast(int)(a - '0')"(to!string(n)));

                      return n;
                     })(b);
    int v = r!"a > b ? a : b"(s);

    writeln(count(s, v) > 1 ? "STALEMATE" : b[countUntil(s, v)]);
}
Jonathan M Davis
fonte
1

Mathematica

Alguns detalhes ainda estão faltando

a = {"ZOO"}; b = {"NO"}
f = FixedPoint[IntegerDigits@Total@# &, #] &

If[(s = f /@ 
        NestWhile[(# /. Max@# -> 0 &) /@ # &, (ToCharacterCode @@ # - 64) & /@ #, 
        f[#[[1]]] == f[#[[2]]] &, 1, 5] &@{a, b})[[1, 1]] > s[[2, 1]], 
   a, b, "STALMATE"]  

{"NO"}
Dr. belisarius
fonte
1

Mathematica 220 207

Depois de escrever isso, notei que isso segue o mesmo raciocínio usado por Belisário,

h@u_ := ToCharacterCode@u - 64;
m@w_ := FromCharacterCode[Most@Sort@h@w + 64];
f@v_ := FixedPoint[Tr@IntegerDigits@# &, Tr@h@v];
x_~g~y_ := If[f@x == f@y, g[m@x, m@y], If[f@x > f@y, 1, 2]];
x_~z~x_ := "STALEMATE";
x_~z~y_ := {x, y}[[x~g~y]] 

Uso

z["ZOO", "NO"]
z["CAN", "BAT"]
z["FAT", "BANANA"]
z["ONE", "ONE"]

resultados

Como a resposta não é competitiva (por muito tempo), decidi usar um formato de entrada mais agradável ao Mathematica.

DavidC
fonte
1

CoffeeScript - 335

z=(a,b,g=a,h=b)->c=y a;d=y b;e=a.length;f=b.length;return g if(c>d);return h if(d>c);return g if(e<2&&f>1);return h if(f<2&&e>1);return "STALEMATE" if(f==e&&f<2);z(x(a),x(b),a,b)
y=(a)->t=0;t+=c.charCodeAt(0)-1 for c in a;t-=9 while 9<t;t
x=(a)->for i in[90..65]
 b=new RegExp(String.fromCharCode(i));return a.replace b, "" if b.test a

Não estou tão feliz com este como eu poderia ter sido, mas eu vou colocá-lo de qualquer maneira. A pontuação real é muito concisa ( yfunção), mas os ifresultados para comparar (em z) são bastante longos.

Para usá-lo, ligue zcom suas duas palavras (por exemplo z 'FOO','BAR'). Ele marcará as duas palavras e retornará a palavra com maior pontuação. Se houver empate, ele será repetido com as palavras modificadas (mantendo os originais retornando eventualmente, daí os dois parâmetros extras) que obtém da xfunção.

O javascript equivalente (expandido) para os interessados:

var x, y, z;

z = function(a, b, g, h) {
  var c, d, e, f;
  if (g == null) {
    g = a;
  }
  if (h == null) {
    h = b;
  }
  c = y(a);
  d = y(b);
  e = a.length;
  f = b.length;
  if (c > d) {
    return g;
  }
  if (d > c) {
    return h;
  }
  if (e < 2 && f > 1) {
    return g;
  }
  if (f < 2 && e > 1) {
    return h;
  }
  if (f === e && f < 2) {
    return "STALEMATE";
  }
  return z(x(a), x(b), a, b);
};

y = function(a) {
  var c, t, _i, _len;
  t = 0;
  for (_i = 0, _len = a.length; _i < _len; _i++) {
    c = a[_i];
    t += c.charCodeAt(0) - 1;
  }
  while (9 < t) {
    t -= 9;
  }
  return t;
};

x = function(a) {
  var b, i, _i;
  for (i = _i = 90; _i >= 65; i = --_i) {
    b = new RegExp(String.fromCharCode(i));
    if (b.test(a)) {
      return a.replace(b, "");
    }
  }
};
Johno
fonte
1

Raquete 479 bytes

(define(dl n)(let p((ol '())(n n))(let-values(((q r)(quotient/remainder n 10)))(if(= q 0)(cons r ol)(p(cons r ol)q)))))
(define(dr N)(let p2((n N))(define s(apply +(dl n)))(if(< s 10)s(p2 s))))
(let p3((l(for/list((i(string->list s)))(-(char->integer i)64)))(k(for/list((i(string->list t)))(-(char->integer i)64))))
(let((a(dr(apply + l)))(b(dr(apply + k))))(cond[(> a b)s][(< a b)t][(equal? l k)"STALEMATE"][else(p3(remove*(list(apply max l))l)(remove*(list(apply max k))k))])))

Ungolfed:

(define (f s t)

  (define (getDigitList n)                     ; sub-fn  to get digit list
    (let loop ((ol '())
               (n n))
      (let-values (((q r) (quotient/remainder n 10)))
        (if (= q 0) (cons r ol)
            (loop (cons r ol) q)))))

  (define (digit_root N)                       ; sub-fn to get digital root of a number
    (let loop2 ((n N))                        
      (define s (apply + (getDigitList n)))    
      (if (< s 10)
          s
          (loop2 s))))

  (let loop3 ((l (for/list ((i (string->list s)))  ; actual fn to compare 2 strings
                   (- (char->integer i) 64)))
              (k (for/list ((i (string->list t)))
                   (- (char->integer i) 64))))
    (let ((a (digit_root (apply + l)))
          (b (digit_root (apply + k))))
      (cond
        [(> a b) s]
        [(< a b) t]
        [(equal? l k) "STALEMATE"]
        [else (loop3 (remove* (list (apply max l)) l)
                     (remove* (list (apply max k)) k)
                     )]
        ))))

Teste:

(f "CAN" "BAT")
(f "ZOO" "NO")

Saída:

"CAN"
"NO"
rnso
fonte
1

PHP, 339 (não especificado), 410 382 359 339 337 bytes

$b=$w=fgetcsv(STDIN);function a($c){for(;a&$g=$c[$p++];)$f+=ord($g)-64;$f=trim($f);for(;$f[1]&a;$f=$h)for($h=0;a&$r=$f[$q++];$h=bcadd($h,$r));return$f;}function d($f){return strtr($f,[max(str_split($f))=>'']);}for(;$c==$d;$b=[$e,$f]){$x=$z++?d:trim;$e=$x($b[0]);$f=$x($b[1]);$c=a($e);$d=a($f);$e||die(STALEMATE);$c!=$d&&die($w[$c<=$d]);}

EDIT 1 : +71 bytes. Usando em STDINvez de fopen('php://stdin','r');e tags curtas. Além disso, total conformidade com as especificações.

EDIT 2 : -28 bytes. Usando em fgetcsv(STDIN)vez de explode(',',trim(fgets(STDIN)))e usado forloop em vez de whileloop.

EDIT 3 : -23 bytes. Funções mescladas ae bmescladas para loops.

EDIT 4 : -20 bytes. Transformado cde recursivo em loop. Em seguida, remova a função ce coloque seu código no espaço para nome global.

EDIT 5 : -2 bytes. Obrigado a @Titus pela -rbandeira.

Élektra
fonte
1
há necessidade de um tag PHP com -rbandeira
Tito
0

JAVA

    public static void main(String args[]) throws Exception{
        String input=(new BufferedReader(new InputStreamReader(System.in)).readLine());
        StringTokenizer st = new StringTokenizer(input, ",");
        String w1 = st.nextToken();String w2 = st.nextToken();int s1=0;int s2=0;
        String flag="";
        do{ Integer sum1=0;Integer sum2=0;
        for (int i=0;i<w1.length();i++)
            sum1+=((int)w1.charAt(i) - 64);
        for (int i=0;i<w2.length();i++)
            sum2+=((int)w2.charAt(i) - 64);
        while (sum1.toString().length()>1){
            s1=0;
            for (int i=0;i<sum1.toString().length();i++)
                s1+=((int)sum1.toString().charAt(i)-48);
            sum1=s1;
        }
        while (sum2.toString().length()>1){
            s2=0;
            for (int i=0;i<sum2.toString().length();i++)
                s2+=((int)sum2.toString().charAt(i)-48);
            sum2 =s2;
        }
        flag=(s1>s2)?w1:(s1!=s2)?w2:"";
        if (flag!="")
            {st = new StringTokenizer(input,",");
                if (s1>s2)
                    System.out.println(st.nextToken());  
                else{
                    st.nextToken();
                    System.out.println(st.nextToken());
                }
            }
        int max=0;
        for (int i=0;i<w1.length();i++){
            max=((int)w1.charAt(i)>max)?(int)w1.charAt(i):max;
        }
        w1 = w1.replace((char)max, (char)64);
        max=0;
        for (int i=0;i<w2.length();i++){
            max=((int)w2.charAt(i)>max)?(int)w2.charAt(i):max;
        }
        w2 = w2.replace((char)max, (char)64);
            }while(flag=="" && !w1.equals(w2)); 
    if (flag.length()<1)
        System.out.println("STALEMATE");
        }
Aman ZeeK Verma
fonte
O código acima substitui todos os caracteres máximos em caso de empate .. é necessário?
Aman ZeeK Verma
0

C ++, 473 (estou pegando emprestado uma chapinha)

#include<iostream>
#define $ string
#define _ return
using namespace std;$ S($&s){int i=-1,m=i,x=0;while(++i<s.length())if(s[i]-'@'>x)m=i,x=s[i];s.erase(m,1);_ s;}int M($ w){int i,v=0;for(i=0;i<w.length();++i)v+=w[i]-'@';while(v>9){i=0;while(v)i+=v-v/10*10,v/=10;v=i;}_ v;}$ B($ x, $ y){while(!(M(x)-M(y)))S(x),S(y);if(M(x)>M(y))_ x;if(M(x)<M(y))_ y;_"STALEMATE";}int main(int c,char**v){$ s;cin>>s;$ x=s.substr(0,s.find(',')),y=s.substr(s.find(',')+1);cout<<B(x,y)<<endl;_ 0;}

Tenho certeza de que poderia encurtá-lo de alguma forma, mas estou cansado.

Editar: originalmente assumiu o argumento da linha de comando, modificado para usar cin. Provavelmente são alguns caracteres a mais agora, mas estou cansado demais para recontá-lo.

Wug
fonte
0

Python: 383 caracteres

execute a função c('CAN','BAT'):

def k(j):
 l=list(j);l.remove(max(j));return''.join(l)
def f(x):
 x=str(x)
 if len(x)==1 and x.isdigit():return int(x)
 return f(sum('ABCDEFGHIJKLMNOPQRSTUVWXYZ'.index(y)+1 for y in x)) if x.isalpha() else f(sum(map(int,x)))
def c(a,b):
 v=f(a);u=f(b);
 if v>u:return a
 if v<u:return b
 return'STALEMATE' if v==u and (len(a)==1 or len(b)==1)else c(k(a),k(b))
Ashwini Chaudhary
fonte
0

F #, 559 533 530 bytes

Ainda não competitivo. Tenho certeza de que c pode ser reduzido, assim como as últimas linhas. Não ter acesso mais fácil aos argumentos da linha de comando também está prejudicando aqui.

open System
let m=Seq.map
let a s=s="";s.ToUpper()|>m(fun c->int c-64)
let rec c i=if i>9 then string i|>m(int>>(-))|>m(fun x->x 48)|>Seq.sum|>c else i
let b i=Seq.fold(fun(r,a)j->(Seq.sum i-a)::r,a+j)([],0)(Seq.sortBy(~-)i)|>fst|>m c
[<EntryPoint>]
let x z=
 let y=z.[0].Split(',')
 let u,v=y.[0].Length,y.[1].Length
 printf"%s"(Seq.fold2(fun s l r->if l=r then 3::s else if l>r then 0::s else 1::s)[](b<|a y.[0])(b<|a y.[1])|>Seq.tryFind((>)3)|>function|None when u>v->y.[0]|None when u<v->y.[1]|Some x->y.[x]|_->"STALEMATE")
 0

Experimente online!

  • Salva 3 bytes restringindo s a string comparando-o com string

Versão ungolfed

open System
let m=Seq.map // this is just to save some characters and I'll use Seq.map for this version

let toIntList s =
    s = "" // constrain s to type string
    s.ToUpper()
    |>Seq.map (fun c -> int c - 64) // converts char value to int and offsets it so that A=1

let rec digitSumUntilSingle i =
    if i > 9 then
        string i                // convert number to string
        |>Seq.map ( int>>(-) )  // convert individual char to int and partially apply substraction
                                // this returns a function
        |>Seq.map (fun x -> x 48) // provide last parameter for substraction, this is equivalent to
                                  // charValue - 48
        |>Seq.sum                 // sum over all digits
        |>digitSumUntilSingle     // recursively call this function again in case we are >9
    else
        i

let calculateDigitalRoot input =
    Seq.fold(fun (result, acc) current ->       // calculate digital root for all possible iterations
                (Seq.sum input - acc)::result,  // basically, this calculates Rule 3 until the end for a given word
                acc + current
            ) ([], 0) (Seq.sortBy (~-) input) // sort input by value descending
    |>fst   // only interested in the lits, not the final accumulator
    |>Seq.map digitSumUntilSingle

[<EntryPoint>]
let main (args) =
    let y = args.[0].Split(',')
    let leftLength = y.[0].Length
    let rightLength = y.[1].Length

    Seq.fold2 (fun state left right ->
                if left = right then
                    3::state
                else if left > right then
                    0::state                // 0 is chosen because this represents y[0] index
                else
                    1::state
               ) [] (calculateDigitalRoot (toIntList y.[0])) (calculateDigitalRoot (toIntList y.[1]))
    |> Seq.tryFind ((>) 3)                  // try to find first variation where left and right digital root isn't equal
    |> function
        | None when leftLength > rightLength -> y.[0]
        | None when leftLength < rightLength -> y.[1]
        | Some x -> y.[x]
        | _ ->"STALEMATE"
    |>printf "%s" 
    0
Brunner
fonte
0

PHP, 296281 267 bytes

function f(&$s){for(;$c=$s[$i++];$m>$c||$m=$c)$p+=ord($c)&31;for($s=str_replace($m,'',$s);9<$p=array_sum(str_split($p)););return$p;}for(list($a,$b)=$x=fgetcsv(STDIN);$s==$t&&$a&$b;$t=f($b))$s=f($a);echo($s-=$t)||($s=strlen($x[0])-strlen($x[1]))?$x[+($s<0)]:STALEMATE;

execute -nou experimente on-line (o TiO inclui quebra).

Em fevereiro de 2011, a versão atual do PHP era 5.3.5; então eu não pude

  • use a atribuição de lista abreviada ( [$a,$b]=fgetcsv(...)e tal)
  • alias count_charsinline
  • a função de índice resulta diretamente
  • use índices de string negativos em vez de substr

Mas nenhum dos dois teria economizado muito; então não importa muito.

As coisas mais caras foram os loops (é claro) e a regra 4 ( 40 36 bytes).

Titus
fonte