Darts trifft Codegolf

11

Ich denke, jeder ist mit Darts vertraut, einige Leute verstehen die Ergebnisse nicht, daher ist für diese Leute hier ein nützlicher Link dazu.

Die Tafel

Eine Dartscheibe kann mit einem in 20 Stücke geschnittenen Kuchen verglichen werden. Jedes Stück ist in 4 Abschnitte unterteilt.

  • ein kleiner äußerer Ring namens double (Punkte x2)
  • ein großer Ring namens Single (Punkte x1)
  • ein weiterer kleiner Ring namens Triple (Punkte x3)
  • ein weiterer großer Ring namens Single (Punkte x1)

In der Mitte des Bretts befinden sich 2 weitere Ringe, ein grüner und ein roter (klassisches Brett).

  • Roter Ring, Mitte des Bretts genannt Bullseye oder Doppelbulle und gut für 50 Punkte. Dieser zählt als Doppelgänger und darf deshalb mit ihm auschecken.
  • Grüner Ring, genannt Stier, einzelner Stier oder einfach 25 und zählt als einzeln.

Herausforderung

Hier finden Sie alle Möglichkeiten zur Kasse mit 3 Pfeilen oder weniger.
Der Benutzer kann eine Ganzzahl eingeben und Sie müssen prüfen, ob es möglich ist, die Punktzahl mit 3 Pfeilen (oder weniger) auf 0 zu bringen.

Beispiele

Beispiel 1:

Input: 170  
Output: T20, T20, Bullseye

Beispiel 2:

Input: 6  
Output: D3;  
        S3,S1,D1;  
        S2,D2;  
        S2,S2,D1;  
        D2,D1;  
        S4,D1;  
        D1,D1,D1;  
        S1,S1,D2;  
        T1,S1,D1;

Beispiel 3:

Input: 169
Output: No possible checkout!

Regeln

  • Grundlegende Dartregel: Sie müssen mit einem Doppel (äußerer Ring des Bretts oder Bullauge) enden.
  • Keine Verwendung externer Ressourcen.
  • Eine harte Codierung möglicher Kassen ist erlaubt, aber denken Sie daran, dass dies ein Codegolf ist, der Ihren Code nicht verkürzt;)
  • Zu treffende Zellen werden im Format C + N angezeigt, wobei C = T für Triple, D für Double und S für Single.
    • bullseye kann bullseye oder DB, DBull oder etwas Ähnliches genannt werden.

Mögliche Kassen

Um Ihnen den Einstieg zu
erleichtern , ist die höchstmögliche Kaufabwicklung 170. 169.168.166.165.163.162.159 sind in 3 Pfeilen nicht möglich.
Die niedrigstmögliche Kasse ist 2.

Zusätzlich

Dies ist keine Voraussetzung. Fügen Sie die Möglichkeit hinzu, alle möglichen Kassen für alle Ergebnisse anzuzeigen. Grundsätzlich, weil ich mich frage, wie viele Kombinationen möglich sind: P.

Der Gewinner ist derjenige mit dem kürzesten Code.

Viel Spaß beim Codieren.

Teun Pronk
quelle
1
Die erste aufgelistete Regel ist falsch (und macht das erste Beispiel ungültig), da Sie auch mit einem Bullen fertig werden können. Es wäre hilfreich zu klären, ob Sie ein Programm, eine Funktion oder beides erwarten. und wie viel Flexibilität es im Ausgabeformat gibt.
Peter Taylor
1
@PeterTaylor Ich werde dies klarer machen, da der grüne Ring und der rote Ring in der Mitte Single Bull und Bullseye oder Double Bull heißen.
Teun Pronk
1
+1 für ausgezeichnete Frage. Dies ist die Art von realem Problem, das Computer gut lösen können. Sie können eine 6 in S2 D1 D1 werfen, die in Ihrer Beispielausgabe fehlt (sie sollte vorhanden sein, es sei denn, Sie betrachten S2 S2 D1 und D1 D1 D1 als gleich, aber sie sind eindeutig als unterschiedlich aufgeführt.) Es gibt einige geringfügige Unklarheiten hinsichtlich des Ausgabeformats und der Zählung der Ergebnisse, auf die ich in meiner Antwort eingehen werde.
Level River St

Antworten:

2

C ++ 248/228 230/214 Zeichen

Rev 0:

int f(int s){char m[4]="SDT";int t=0;for(int b=2;b<77;b+=1+(b==62)*12)for(int a=2;a<77;a+=1+(a==62)*12){int c=s-a/3*(a%3+1)-b/3*(b%3+1);if(((c+38)/40==1)|(c==50)&&(c%2==0)&(a>=b)){printf("%c%d %c%d D%d\n",m[a%3],a/3,m[b%3],b/3,c/2);t++;}}return t;}

Rev 1. Einige Zeichen wurden gespeichert, indem alle Variablen gleichzeitig deklariert und unnötige Klammern entfernt wurden. Es stellt sich heraus, dass in C ++ alle logischen und bitweisen und / oder Vorrang vor Vergleichen haben.

int f(int s){char m[4]="SDT";int a,b,c,t=0;for(b=2;b<77;b+=1+(b==62)*12)for(a=2;a<77;a+=1+(a==62)*12){c=s-a/3*(a%3+1)-b/3*(b%3+1);if(c>1&c<41|c==50&&c%2==0&a>=b){printf("%c%d %c%d D%d\n",m[a%3],a/3,m[b%3],b/3,c/2);t++;}}return t;}

Ich habe eher eine Funktion als ein Programm ausgeführt, wie es andere getan haben. Es gibt die Gesamtzahl der gefundenen Möglichkeiten zurück. Es kann von 230 auf 214 Zeichen reduziert werden, indem die Totalisierungsfunktion entfernt wird.

Beispielausgabe, Punktzahl 6:

Geben Sie hier die Bildbeschreibung ein

Ich zähle verschiedene erste und zweite Pfeile als dieselbe Kombination, wie es das OP getan hat (Beispiel:

T1 S1 D1 = S1 T1 D1), obwohl dies zusätzliche 7 Zeichen kostet. Ich liste immer zuerst die höhere Punktzahl auf (ohne das Verdoppeln und Verdreifachen), da ich denke, dass dies für den Spieler relevanter ist (der seine Strategie ändern kann, wenn er mit dem ersten Pfeil verfehlt). Aus dem gleichen Grund liste ich die Pfeile in der Reihenfolge auf der zweite Pfeil. Ich betrachte den 3. Pfeil als völlig anders als die beiden anderen, daher betrachte ich D1 D2 und D2 D1 als unterschiedliche Fälle, während das OP sie als gleich auflistet.

Mit diesem Zählsystem erhalte ich insgesamt 42336 Möglichkeiten , genau wie bei mmumboss. Wenn verschiedene erste und zweite Pfeile als unterschiedliche Kombinationen gezählt werden, geht dies bis zu 83349.

Ich habe keine for-Schleife mit Mengen verwendet, wie andere es getan haben (ich bin ziemlich neu in C ++ und ich weiß nicht einmal, ob es möglich ist.) Stattdessen missbrauche ich eine Bedingung im Schleifeninkrement, um von 20 auf 25 zu springen Ich verwende die Variable aus einer einzelnen Schleife, um alle möglichen Punkte für einen einzelnen Pfeil zu codieren, wie folgt: S1 D1 T1 S2 D2 T2 usw. mit Modul und Division zum Decodieren. Dies spart die Ausführlichkeit, mehr für Schleifen zu deklarieren, obwohl es Ausdrücke komplizierter macht.

Das Ergebnis ist, dass ein unbenutzter Pfeil als T0 angezeigt wird, aber ich denke, es ist klar, was gemeint ist, zumal ich (indem ich verschiedene erste und zweite Pfeile als dieselbe Kombination betrachtet habe) sie zu Beginn alle zusammen gruppieren konnte meiner Ausgabe.

Ungolfed Version hier. Einige andere Funktionen sind die selektive Verwendung der Operatoren & und && mit | so, dass die gewünschte Rangfolge ohne Klammern angegeben wird.

int f(int s)
{
  char m[4] = "SDT";
  int a,b,c,t=0;
    for (b = 2; b < 77; b += 1 + (b == 62) * 12)
      for (a = 2; a < 77; a += 1 + (a == 62) * 12){
        c = s - a / 3 * (a % 3 + 1) - b / 3 * (b % 3 + 1);
        if (c>1 & c<41 | c == 50 && c % 2 == 0 & a >= b){
          printf("%c%d %c%d D%d\n", m[a % 3], a / 3, m[b % 3], b / 3, c / 2);
          t++;
        }
     }
   return t;
}
Level River St.
quelle
204 Bytes
Deckenkatze
4

MATLAB ( 299 249 241 Zeichen)

Dies ist mein erstes ernstes Golfen. Mein erster Versuch (136 Zeichen) liefert das richtige Ergebnis, aber nicht mit der richtigen Formatierung. Es gibt alle Möglichkeiten, die Anzahl der Punkte für jeden Pfeil zu betrachten. Dies bedeutet, dass Single 20 und Double 10 einen separaten Eintrag haben, beide jedoch als 20 angezeigt werden. Natürlich ist der letzte Pfeil immer ein Double.

function f(x);u=[1:20 25].';y=[u;2*u; 3*u(1:end-1)];v=combvec([combnk(y,2);[y y];[zeros(62,1) y];[0 0]].',y(22:42).').';v(sum(v,2)==x,:)

Im zweiten Versuch wird die Formatierung verbessert, was natürlich die Anzahl der Zeichen erhöht hat:

function f(x);h=.1;u=h+[1:20,25].';y=[u;2*u;3*u(1:20)];v=combvec([combnk(y,2);[y,y];h*ones(62,1),y];[h,h]].',y(22:42).').';t='SDT';r=@fix;strrep(arrayfun(@(x)[t(int8((x-r(x))/h)),num2str(h*r(x)/(x-r(x)))],v(sum(r(v),2)==x,:),'un',0),'S0','')

Verbessert von 299 auf 249 Zeichen bei gleichzeitiger Verbesserung der Ausgabeformatierung. Für diese verbesserte Version lautet die Ausgabe für die Beispielfälle:

f (170):

'T20'    'T20'    'D25'

f (6):

'S1'    'S3'    'D1'
'S1'    'T1'    'D1'
'S2'    'D1'    'D1'
'S2'    'S2'    'D1'
'D1'    'D1'    'D1'
''      'S4'    'D1'
''      'D2'    'D1'
'S1'    'S1'    'D2'
''      'S2'    'D2'
''      'D1'    'D2'
''      ''      'D3'

f (169):

Empty cell array: 0-by-3

Zusätzlich:

Nach meinen Berechnungsfähigkeiten gibt es insgesamt 42336 Möglichkeiten, das Dartspiel zu beenden.

mmumboss
quelle
Das Ergebnis sollte zeigen, welche Zelle getroffen werden soll, also sollte es im ersten 60 60 50sein T20 T20 Bullseye. Ich werde dies in der Frage klarer machen. Gut gemacht, fast da :)
Teun Pronk
1
Ja, darauf habe ich schon hingewiesen. Dies ist der erste unvollendete Versuch. ;)
mmumboss
Ups sorry lol, ich war zu neugierig auf den Code und das Ergebnis Ich habe die Geschichte über xD nicht gelesen
Teun Pronk
Das sollte besser sein. Ich kann mir nur vorstellen, dass der Bulle immer noch als 25 angezeigt wird. Aber ich hoffe, das ist in Ordnung, da es sonst keine andere Möglichkeit gibt, als dies hart zu codieren, was einfach keinen Spaß macht.
mmumboss
Einzelner Bulle als 25 ist in der Tat akzeptabel, es ist die einzige Möglichkeit, 25 mit 1 Pfeil zu werfen
Teun Pronk
2

Rubin (260 Zeichen)

"Das letzte sollte ein Doppel sein" war das fehlende Stück - konnte nicht herausfinden, warum 168 keine Ergebnisse haben sollte ...:

c=->n,d=3{d=d-1;r=[];n==0?[r]:(d>=0&&n>0?(o='0SDT';((1..20).map{|p|(1..3).map{|h|c.(n-p*h,d).map{|m|r<<["#{o[h]}#{p}"]+m}}};c.(n-50,d).map{|m|r<<['DB']+m};c.(n-25,d).map{|m|r<<[?B]+m})):1;r.select{|*i,j|j[?D]}.tap{|x|d!=2?1:puts(x.map{|i|"#{i.join(?,)};"})})}

c. (170)

T20,T20,DB;

c. (6)

S1,S1,D2;
S1,T1,D1;
S1,S3,D1;
D1,D1,D1;
D1,S2,D1;
D1,D2;
T1,S1,D1;
S2,D1,D1;
S2,S2,D1;
S2,D2;
D2,D1;
S3,S1,D1;
D3;
S4,D1;
Uri Agassi
quelle
1

Python 2.7 (270 Zeichen)

Ich bin mir nicht sicher, ob Python einen Einzeiler zulässt, aber er ist in drei.

def f(n):
 a={'%s%s'%('0SDT'[i],n):n*i for n in range(1,21)+[25] for i in [1,2,3] if n*i<75};a['']=0
 for r in [' '.join(h[:3]) for h in [(x,y,z,a[x]+a[y]+a[z]) for x in a for y in a for z in {k:a[k] for k in a if 'D' in k}] if h[3]==n and len(h[0])<=len(h[1])]:print r

Oder mehr als 278 Zeichen mit der richtigen Meldung "No Checkout" (z. B. 290 hier):

def f(n):
 a={'%s%s'%('0SDT'[i],n):n*i for n in range(1,21)+[25] for i in [1,2,3] if n*i<75};a['']=0;
 for r in [' '.join(h[:3]) for h in [(x,y,z,a[x]+a[y]+a[z]) for x in a for y in a for z in {k:a[k] for k in a if 'D' in k}] if h[3]==n and len(h[0])<=len(h[1])] or ['No Checkout']:print r

Auf geht's:

f (170)

T20 T20 D25

f (6)

S3 S1 D1
S2 S2 D1
S2 D1 D1
S1 S3 D1
S1 S1 D2
S1 T1 D1
 S2 D2
 S4 D1
  D3
 D2 D1
 D1 D2
T1 S1 D1
D1 S2 D1
D1 D1 D1

f (169)

No Checkout

Dinge, mit denen ich nicht zufrieden bin:

for x in a for y in a for z in

Dies sind über 10% der Gesamtmenge. Gibt es einen kompakteren Weg ohne itertools etc?

and len(h[0])<=len(h[1])

Dies wird verwendet, um Duplikate bei einem Zwei-Pfeil-Finish zu vermeiden (z. B. ['', 'S1', 'D1'] und ['S1', '', 'D1']). Ich halte Ordnung für wichtig (hey - der letzte Pfeil muss ein Doppelpfeil sein, also ist Ordnung eindeutig wichtig), aber der Nichtwurf ist ein Sonderfall.

psion5mx
quelle
1

05AB1E , 43 Bytes

20L25ª3Lâ¨Ðʒθ<}Uã«XâXìε˜2ô}ʒPOQ}εε`…TSDsèì

Ziemlich langsam. Gibt als Liste von Listen oder als leere Liste aus, wenn kein Abschluss möglich ist. Meine Bullen sind S25und D25; Wenn dies nicht erlaubt ist, kann ich es ändern.

Probieren Sie es online aus oder überprüfen Sie einige Testfälle gleichzeitig .

Erläuterung:

Es gibt ein paar Schritte:

1) Erstellen Sie eine Liste aller möglichen Einzel-, Doppel- und Dreifachpfeile:

20L         # Create a list in the range [1,20]
   25ª      # Append 25 to this list
      3L    # Create a list in the range [1,3]
        â   # Create all possible pairs of these two lists
         ¨  # Remove the last pair (which is the Triple Bull)
            # Now we have a list of all possible darts:
            #  [[1,1],[1,2],[1,3],[2,1],...,[20,3],[25,1],[25,2]]

2) Holen Sie sich alle möglichen Finisher (die mit einem Double enden) von bis zu 3 Darts:

Ð           # Triplicate this list
 ʒ  }       # Filter the top copy by:
  θ         #  Where the last value
   <        #  Decremented by 1 is truthy (==1), so all doubles
     U      # Pop this filtered list of doubles, and store it in variable `X`
 ã          # Create all possible pairs of the list of darts with itself
  «         # Merge it with the list of darts
            # We now have a list containing all possible variations for 1 or 2 darts
 Xâ         # Then create all possible pairs of these with the doubles from variable `X`
   Xì       # And prepend the doubles themselves as well
            # Now we have all possible variations of 1 double; 1 dart + 1 double;
            # or 2 darts + 1 double
     ε   }  # Map each to:
      ˜     #  Deep-flatten the list
       2ô   #  And split it into parts of size 2
            #  (this is to convert for example a 2 darts + 1 double from
            #   [[[20,3],[5,1]],[1,2]] to [[20,3],[5,1],[1,2]])
            # Now we have a list of all possible finishers of up to 3 darts

3) Behalten Sie nur diejenigen bei, für die die Gesamtpunktzahl der Eingabe-Ganzzahl entspricht:

ʒ   }       # Filter this list by:
 P          #  Get the product of each inner-most lists
            #   i.e. [[20,3],[5,1],[1,2]] → [60,5,2]
  O         #  Take the sum of those
            #   i.e. [60,5,2] → 67
   Q        #  Check if this value is equal to the (implicit) input-integer
            # Now we only have the finishers left with a total value equal to the input

4) Konvertieren Sie die Daten in die hübsch gedruckte Ergebnisliste (dh [[20,3],[5,1],[1,2]]wird ["T20","S5","D2"]):

ε           # Map each of the remaining finishers of up to 3 darts to:
 ε          #  Map each inner list to:
  `         #   Push both values separately to the stack ([20,3] → 20 and 3)
   TSD     #   Push string "TSD"
       s    #   Swap to get the integer for single/double/triple at the top of the stack
        è   #   Use it to index into the string
            #   NOTE: 05AB1E has 0-based indexing with automatic wraparound,
            #   so the triple 3 will wrap around to index 0 for character "T"
         ì  #   Prepend this character in front of the dart-value
            # (after which the result is output implicitly as result)
Kevin Cruijssen
quelle
0

Kotlin , 254 Bytes

Hinweis: Der Algorithmus basiert auf der C ++ - Antwort von Level River St.

{s:Int->val m="SDT"
var c=0
val r=(2..62).toList()+listOf(75,76)
for(t in r)for(o in r){val l=s-o/3*(o%3+1)-t/3*(t%3+1)
if((l>1&&l<41||l==50)&&l%2==0&&o>=t){println("${m[o%3]}${o/3},${m[t%3]}${t/3},D${l/2}")
c++}}
if(c<1)println("No possible checkout!")}

Probieren Sie es online aus!

JohnWells
quelle