Kann meine 4-Noten-Spieluhr das Lied abspielen?

51

Ich habe eine kurbelbetätigte Spieluhr, die eine Serie von vier Noten spielen kann. Wenn ich die Kurbel drehe, zupft sie eine von vier Saiten, abhängig von der Position der Kurbel und der Drehrichtung. Wenn die Kurbel genau nach Norden gedreht wird, sieht die Box (mit den Saiten 1 bis 4) folgendermaßen aus:

1  |  2
   |
   O   

4     3

Von dort aus kann ich die Kurbel im Uhrzeigersinn drehen, um die Saite 2 zu zupfen und die Kurbel nach Osten zu richten:

1     2

   O---   

4     3

Alternativ hätte ich auch die Kurbel von Norden gegen den Uhrzeigersinn drehen können, um die erste Saite zu spielen und mit einer nach Westen weisenden Kurbel zu enden:

1     2

---O   

4     3

Zu jeder Zeit kann die Box dann eine von zwei Noten spielen: die nächste verfügbare Note im Uhrzeigersinn oder die nächste Note gegen den Uhrzeigersinn.

Herausforderung

Ihre Herausforderung besteht darin, ein Programm oder eine Funktion zu schreiben, die eine nicht leere Folge von Notenwerten (dh Ziffern 1bis 4) akzeptiert, und festzustellen, ob es jemals möglich ist, diese Notenfolge auf der Spieluhr abzuspielen. Produzieren Sie ein wahres oder falsches Ergebnis, um die Spielbarkeit oder Nichtspielbarkeit der Eingabe anzuzeigen.

Einige Notizen:

  • Die Eingabe macht keine Annahmen über die anfängliche Startposition. Die Eingaben 214(von Osten ausgehend und streng gegen den Uhrzeigersinn bewegend) und 234(von Norden ausgehend und streng im Uhrzeigersinn bewegend) und beide sind gültig.

  • Die Kurbel kann sich nach jeder Note frei in beide Richtungen bewegen. Eine Reihe derselben Note ist möglich (zB 33333), indem man sich über eine Saite vor und zurück bewegt. Die Serie 1221441ist perfekt spielbar (von Westen aus zwei Schritte im Uhrzeigersinn, dann drei Schritte gegen den Uhrzeigersinn und dann zwei Schritte im Uhrzeigersinn).

Proben

Einige trueFälle:

1
1234
1221
3333
143332
22234
2234
22214
1221441
41233

Einige falseFälle:

13     (note 3 is never available after note 1)
1224   (after `122`, the crank must be north, so 4 is not playable)
121    (after `12` the crank is east; 1 is not playable)
12221  (as above, after `1222` the crank is east)
43221  
Apsillers
quelle
Kann die Eingabe die Zeichenfolge einschließlich Anführungszeichen sein?
Luis Mendo
@ LuisMendo Sicher, ich werde es zulassen - ich interessiere mich für Ihren Algorithmus und bringe Sie nicht dazu, durch Rahmen zu springen, um die Eingabe zu erhalten. Wie auch immer, es gibt inoffiziellen Community-Konsens darüber, dass es im Allgemeinen in Ordnung ist: String-Eingabe mit oder ohne ""?
Apsillers
1
Ich wusste das nicht. Danke für den Link!
Luis Mendo
1
@AJMansfield Nein, Lösungen sollten beliebig viele Zyklen zulassen. Wenn durch eine Eingabe Ihr Code ein Limit im Interpreter Ihrer Sprache oder im Arbeitsspeicher Ihres Computers überschreitet, ist das natürlich in Ordnung (da es nur durch den physisch vorhandenen Arbeitsspeicher oder den vom Interpreter zugelassenen Speicher begrenzt ist), aber Ihre Lösung sollte keine zusätzlichen Einschränkungen auferlegen wie weit oder wie oft sich die Kurbel bewegt.
Apsillers
1
Diese Herausforderung hat die Kategorie Nicht so einfach wie es aussieht in Best of PPCG 2016 gewonnen. Leider können wir Herausforderungen nicht mit Kopfgeldern belohnen , aber Zgarb hat eine Herausforderung zu Ihren Ehren geschrieben . Herzliche Glückwünsche!
Martin Ender

Antworten:

9

Pyth, 30 27 Bytes

f!-aVJ.u%-ysYN8zTtJ,1 7cR2T

Hier ist die Idee:

 1.5  1  0.5

  2       0

 2.5  3  3.5

Die Kurbel befindet sich immer in einer halben Ganzzahlposition c. Bei jedem Schritt spiegeln wir es ndurch Setzen über eine ganzzahlige Positionsnote wider c = 2*n-c. Wenn ngültig, cändert sich um ± 1 mod 8. Wenn nungültig, cändert sich um ± 3 mod 8. Wir reduzieren die Eingabe kumulativ, um alle Werte von zu erfassen c, und prüfen dann, ob alle Noten gültig waren. Wir machen das für jeden Startwert von c, weil er kürzer ist als nur die, die an die erste Note angrenzen.

Formatiert:

f
  ! -
      aV J .u
              % -
                  y s Y
                  N
                8
              z
              T
         t J
      ,
        1 
        7
  cR2 T

Testsuite .

Lirtosiast
quelle
18

CJam, 34 31 Bytes

8,q{~2*f{_@-_zF8b&,@@+8,=*}0-}/

Hab das auf meinem Handy gemacht, deshalb muss ich später eine Erklärung abgeben. Die Ausgabe ist nicht leer, wenn die Wahrheit stimmt.

Versuchen Sie es online | Testsuite

Erläuterung

Der neue Code verschiebt das Layout ein wenig:

2    3    4

1    .    5

0/8  7    6

Gerade Zahlen entsprechen Saitenpositionen und ungerade Zahlen entsprechen Kurbelpositionen.

Folgendes passiert:

8,           Create the range [0 1 .. 7] of possible starting positions
             We can leave the string positions [0 2 4 6] in since it doesn't matter
q{ ... }/    For each character in the input...
  ~2*          Evaluate as integer and double, mapping "1234" -> [2 4 6 8]
  f{ ... }     Map over our possible current crank positions with the string
               position as an extra parameter
    _@-          Calculate (string - crank), giving some number in [-7 ... 7]
    _z           Duplicate and absolute value
    F8b          Push 15 base 8, or [1 7]
    &,           Setwise intersection and get length. If (string - crank) was in
                 [-7 -1 1 7] then the move was valid and this evaluates to 1, otherwise 0
    @@+          Calculate ((string - crank) + string)
    8,=          Take modulo 8, giving the new crank position. x%y in Java matches the
                 sign of x, so we need to do ,= (range + index) to get a number in [0 .. 7]
    *            Multiply the new crank position by our previous 0 or 1
  0-           Remove all 0s, which correspond to invalid positions

Der Stapel wird dann am Ende automatisch gedruckt. Mögliche Endpositionen befinden sich im Ausgang, z. B. für den Eingang ist 1der Ausgang 31, dh die Kurbel kann nach links oder oben zeigen.

Wenn nur CJam Filter mit extra Parameter hätte ...


Bearbeiten: Vorübergehendes Zurücksetzen, während ich mich davon überzeugt habe, dass dieses 29-Byte-Format funktioniert:

8,q{~2*f{_@-_7b1#@@+8,=|}W-}/
Sp3000
quelle
37
Jedes Mal, wenn jemand mit einer schwierigen Sprache wie cjam antwortet und sagt "Hab das auf meinem Handy gemacht", sterbe ich innerlich ein wenig
Dennis van Gils
2
Er meinte wahrscheinlich, dass der Text mit einem Telefon ausgegeben wurde, aber das geschah in seinem Kopf.
Nelson
7

Haskell, 93 88 87 Bytes

any(all(\(a,b:c)->1>mod(a!!1-b)4).(zip=<<tail)).mapM((\a->[[a,a+1],[a+1,a]]).read.pure)

Dies wird zu einer anonymen Funktion ausgewertet, die eine Zeichenfolge akzeptiert und einen Booleschen Wert zurückgibt. Testsuite hier.

Erläuterung

Die Idee ist, dass das Lambda auf der rechten Seite eine Zahl azuordnet [[a,a+1],[a+1,a]], die zwei möglichen "Bewegungen", die die Kurbel über diese Zahl führen, gemäß dem folgenden Diagramm:

  1 (2) 2

(1/5)  (3)

  4 (4) 3

In der anonymen Hauptfunktion wird zunächst mapM((...).read.pure)jedes Zeichen in eine Ganzzahl konvertiert, das obige Lambda darauf angewendet und einer der beiden Züge ausgewählt, wobei die Liste aller resultierenden Zugsequenzen zurückgegeben wird. Dann prüfen wir, ob eine dieser Sequenzen die Eigenschaft hat, dass die zweite Nummer jeder Bewegung der ersten Nummer der nächsten Modulo 4 entspricht, was bedeutet, dass es sich um eine physikalisch mögliche Sequenz handelt. Dazu verschieben wir zipjede Sequenz mit ihrer tail, überprüfen die Bedingung für alldie Paare und prüfen , ob die anySequenz den Wert ergibt True.

Zgarb
quelle
7

Netzhaut, 50 Bytes

A`13|31|24|42|(.)(?!\1)(.)(\2\2)*(\1|\2(?!\1|\2).)

Ich denke das funktioniert?

Probieren Sie es hier aus.

jimmy23013
quelle
6

Retina , 127 109 Bytes

^((1|2)|(2|3)|(3|4)|(4|1))((?<2-5>1)|(?<5-2>1)|(?<3-2>2)|(?<2-3>2)|(?<4-3>3)|(?<3-4>3)|(?<5-4>4)|(?<4-5>4))*$

Dies druckt 0oder 1entsprechend.

Probieren Sie es online! (Dies ist eine leicht modifizierte Version, die alle Übereinstimmungen in der Eingabe markiert, anstatt 0oder zu drucken 1.)

Ich habe versucht, einen eleganten Algorithmus zu entwickeln, aber meine ersten Versuche waren nicht in der Lage, das Backtracking zu umgehen ... und das Backtracking zu implementieren, ist ärgerlich ... also habe ich eine Sprache verwendet, die das Backtracking für mich ausführt, bei der ich nur a codieren muss gültige Lösung. Leider ist die Kodierung ziemlich ausführlich und ziemlich überflüssig ... Ich bin sicher, dass dies verkürzt werden kann.

Während ich versuche, etwas besseres herauszufinden, ist hier eine etwas besser lesbare Version, wenn jemand herausfinden möchte, wie das funktioniert:

^
(
    (?<a>1|2)
  | (?<b>2|3)
  | (?<c>3|4)
  | (?<d>4|1)
)
(
    (?<a-d>1) | (?<d-a>1)
  | (?<b-a>2) | (?<a-b>2)
  | (?<c-b>3) | (?<b-c>3)
  | (?<d-c>4) | (?<c-d>4)
)*
$

Und hier ist ein Hinweis:

1  a  2

d  O  b

4  c  3
Martin Ender
quelle
6

MATL , 57 55 Bytes

1t_hjnZ^!t1tL3$)2_/wvG1)UGnl2$Ov+Ys.5tv3X53$Y+4X\G!U=Aa

Hierbei wird die aktuelle Version (10.2.1) verwendet , die älter als diese Herausforderung ist.

BEARBEITEN (17. Januar 2017): Aufgrund von Änderungen in der Sprachev muss durch &vund tL3$)durch ersetzt werden Y)(außerdem könnten einige andere Verbesserungen vorgenommen werden). Der folgende Link enthält diese beiden Änderungen

Probieren Sie es online!

Erläuterung

Dies basiert auf zwei meiner Lieblingswerkzeuge für Codegolf: Brute Force und Convolution .

Der Code legt den Weg durch die Kurbel in Bezug auf den Koordinaten folgen 0.5, 1.5usw. Jede Zahl gibt die Position der Kurbel zwischen den Noten. Der Code erstellt zunächst ein Pfadarray mit allen möglichen Pfaden, die mit der ersten Note der Eingabezeichenfolge beginnen. Jeder Pfad ist eine Spalte in diesem Array. Dies ist die Brute-Force- Komponente.

Aus diesem Pfadarray wird ein Notenarray erhalten, bei dem jede Spalte eine realisierbare Folge von gespielten Noten ist. Wenn Sie sich beispielsweise von einer Position 0.5zur 1.5nächsten bewegen , wird eine Note erzeugt 1. Dies besteht darin, den Durchschnitt zwischen Positionen zu bilden und dann eine Modulo-4-Operation anzuwenden. Der laufende Durchschnitt entlang jeder Spalte wird mit einer 2D- Faltung erstellt .

Schließlich prüft das Programm, ob eine Spalte des Notenarrays mit der Eingabe übereinstimmt.

1t_h        % row array [1, -1]
j           % input string
nZ^!        % Cartesian power of [1, -1] raised to N, where "N" is length of string
t           % duplicate
1tL3$)      % extract first row
2_/         % divide by -2
wv          % attach that modified row to the top of Cartesian power array
G1)U        % first character of input string converted to number, "x"
Gnl2$O      % column array of N-1 zeros, where N is length of input
v           % concat vertically into column array [x;0;0...;0]
+           % add with singleton expansion
Ys          % cumulative sum along each column. Each column if this array is a path
.5tv        % column array [.5;.5]
3X5         % predefined string 'same' (for convolution)
3$Y+        % 2D convolution of path array with [.5;.5]
4X\         % modified modulo operation. This gives note array with values 1,2,3,4
G!U         % column array of input string characters converted to numbers
=Aa         % true if any column of the note array equals this
Luis Mendo
quelle
5

Pyth, 43

Km-R2sMdc`M%R4-VJjQTtJ`0|Fm!s-VKdCm_B^_1dlK

Test Suite

Dies ist wahrscheinlich sehr golffähig und auch nicht der optimale Algorithmus für das Golfen (ich erwarte, dass die Aufzählung aller Pfade kürzer sein wird?) ... Wie auch immer, wenn Sie einen Fehler mit dem Algorithmus finden, lassen Sie es mich bitte wissen, ich denke, es sollte funktionieren, aber ich habe mich vorher geirrt!

Ich erkläre meinen Algorithmus anhand der Beispieleingabe von 1221. Dieses Programm bildet zunächst die Ziffern gegen ihre Nachfolger, etwa so: [[1,2],[2,2],[2,1]]. Dann wird es ihre Differenzen mod 4(Pyth wird das Ergebnis , das das Vorzeichen des rechten Arguments übereinstimmt %, so dass diese immer positiv ist): [3,0,1]. Dann werden die Ergebnisse aufgeteilt auf 0und haben 2von jedem von ihnen abgezogen: [[1],[-1]].

Nachdem das Setup abgeschlossen ist, erstellen wir eine Liste von [-1,1,-1...]und deren Negation [1,-1,...], die beide dieselbe Länge haben wie das resultierende Array von zuvor. Führen Sie dann für jede dieser Listen eine Zwischensubtraktion zwischen den Elementen der Liste und der im vorherigen Schritt erstellten Liste durch. Wenn dann eines der Ergebnisse nur leere Listen enthält, geben wir true aus.

FryAmTheEggman
quelle
Was meinst du mit "die Ergebnisse werden auf 0 aufgeteilt"? Was würden Sie insbesondere für 1221221und bekommen 1221441?
Neil
1
@Neil 1221221ist falsch und 1221441gibt insgesamt wahr, aber wenn ich verstehe, möchten Sie das Ergebnis nach diesem Schritt im Algorithmus? Wenn das der Fall ist, gibt es: von [3, 0, 1, 3, 0, 1]bis [[3], [1, 3], [1]]und [3, 0, 1, 1, 0, 3]bis [[3], [1, 1], [3]]. Lassen Sie mich wissen, wenn Sie etwas anderes erklärt haben möchten :)
FryAmTheEggman
Ich glaube, ich bin verwirrter als zuvor. Könnten Sie diese beiden Beispiele bitte beenden, um zu erklären, wie die (richtigen) Ergebnisse erzielt werden?
Neil
1
@Neil Sicher, kein Problem :) Von dort aus nehmen wir die Subtraktion vor: [[1], [-1, 1], [-1]]und [[1], [-1, -1], [1]]von hier aus können Sie sehen, dass die erste Liste keine Listen enthält, die sich abwechseln -1und 1die andere Liste das Endergebnis liefert. Der Algorithmus ist ein bisschen stumpf, aber er ordnet Richtungsänderungen 0und Richtungen wie folgt zu. +/-1Dann wird überprüft, ob keine Sprünge gemacht werden und die Richtungen sinnvoll sind.
FryAmTheEggman
Oh, also das bisschen, das mir gefehlt hat, war, dass jede Teilungsliste aus demselben Wert bestehen muss und diese Werte sich abwechseln müssen. Vielen Dank!
Neil
4

Matlab, 279 180 Bytes

o=eye(4);a=input('')-'0';M=[o,o(:,[4,1:3]);o(:,[2:4,1:4,1])];x=2;for p=[a(1),mod(a(1),4)+1];for k=a;i=find(M*[o(:,k);o(:,p)]>1);if i;p=mod(i-1,4)+1;else;x=x-1;break;end;end;end;x>0

Eine ziemlich faule Lösung, aber die kürzeste, die ich finden konnte. Ich habe eine spezielle Matrix erstellt: Wenn Sie den Zustand des Zupfers und die letzte zu zupfende Zeichenfolge codieren, wird ein Vektor zurückgegeben, der die neue Position des Zupfers codiert und angibt, ob der vorherige Zupfvorgang überhaupt möglich war. Jetzt durchlaufen wir alle Noten von den zwei möglichen Startpositionen und prüfen, ob eine davon zu einer spielbaren Melodie führt. Kann wahrscheinlich viel mehr golfen werden.

Erweiterte und erläuterte Quelle:

o=eye(4);
a=input('')-'0';

% encoding of plucker/notes
%      1
%   1     2
%4           2
%   4     3
%      3
%

M=[...
%12 3 4 1 2 3 4 <
1,0,0,0,0,1,0,0; %1  k = current note
0,1,0,0,0,0,1,0; %2  
0,0,1,0,0,0,0,1; %3  
0,0,0,1,1,0,0,0; %4  
0,0,0,1,0,0,0,1; %1  p = current position of plucker
1,0,0,0,1,0,0,0; %2
0,1,0,0,0,1,0,0; %3
0,0,1,0,0,0,1,0];%4
% the vector we multiply with this matrix has following structure,
% the k-th and the p+4 th entries are 1, the rest 0
% when we multiply this vecotr with this matrix, we get a vector with an
% entry of value 2 IF this is a valid move ( mod(positionOfThe2 -1,4)+1 is
% the position of the plucker now)
% or only entries less than 2 it is impossible
x=2;  %number of "chances" to get it right
for p=[a(1),mod(a(1),4)+1] %check both starting values;
    for k=a;                %loop throu the notes
        size(M);

        c = M * [o(:,k);o(:,p)];
        i=find(c>1);               %did we find a 2?
        if i;
           p=mod(i-1,4)+1;         %if yes, valid move
        else;
            x=x-1;                 %if no, invalid, 
            break;
        end 
    end
end
x=x>0 %if we failed more than once, it is not possible
fehlerhaft
quelle
4

ES6, 104 100 Bytes

s=>!/13|24|31|42|3[24]{2}1|4[13]{2}2|1[24]{2}3|2[13]{2}4|(.).\1/.test(s.replace(/(.)(\1\1)+/g,"$1"))

Bearbeiten: 4 Bytes dank @DigitalTrauma gespeichert.

Dies ist eine vollständige Neufassung, da mein bisheriger Ansatz fehlerhaft war.

Ich beginne damit, dass ich alle Ziffernreihen auf 1 oder 2 reduziere, je nachdem, ob der Lauf eine gerade oder eine ungerade Zahl enthält. Ich suche dann nach allen illegalen Kombinationen:

  • 13|24|31|42 (gegenüberliegende Seiten)
  • 3[24]{2}1wie 3221und 3441sind illegal
  • ähnlich für 4xx2, 1xx3und 2xx4wo xist eine der fehlenden Ziffern
  • (.).\1wie Dinge 121illegal sind ( 111wurde auf früher reduziert 1)

Wenn es keine illegalen Paare oder "Tripel" gibt, ist die gesamte Kette legal (der Beweis durch Induktion bleibt als Übung, da es hier spät in der Nacht ist).

Ich habe versucht, 3[24]{2}1|1[24]{2}3mit einer negativen Lookahead-Behauptung zu vereinfachen , aber es stellte sich heraus, dass dies länger war.

Neil
quelle
f("1122") => true@DigitalTrauma
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Daran sehe ich nichts auszusetzen. Andererseits ist mir klar geworden, dass f("1221221")die Antwort falsch ist, also muss ich überdenken.
Neil
Es ist immer schön, eine Testsuite beizufügen, '43221' schlägt fehl: jsbin.com/vafitotequ/1/edit?js,console
Pavlo
@Pavlo Hoppla, ich hatte Golf gespielt [24][24], (2|4)\1aber nicht ausreichend getestet. Das tut mir leid.
Neil
Können Sie Golf [24][24]zu [24]{2}?
Digitales Trauma
2

JavaScript (ES6), 80 Byte

s=>[r=0,1,2,3].map(i=>[...s].map(n=>n-1-i%4?n%4-i%4?v=0:i+=3:i++,v=1)|v?r=1:0)|r

Erläuterung

i%4 ist die aktuelle Kurbelposition:

    1 (i%4 == 1) 2   

(i%4 == 0) (i%4 == 2)

    4 (i%4 == 3) 3   

Eingerückt und kommentiert

s=>
  [r=0,1,2,3].map(i=> // i = crank position, test for i starting at 0 to 3, r = result
    [...s].map(n=>    // for each note n
      n-1-i%4?        // if n is not at the position after i
        n%4-i%4?      // if n is not at the position before i
          v=0         // set the result of this test to invalid
        :i+=3         // else i-- (+3 used because i%4 would break for negative values)
      :i++,           // else i++
      v=1             // v = result of test, initialise to 1 (valid)
    )
    |v?r=1:0          // if the test returned true, set the result to true
  )
  |r                  // return the result

Prüfung

var solution = s=>[r=0,1,2,3].map(i=>[...s].map(n=>n-1-i%4?n%4-i%4?v=0:i+=3:i++,v=1)|v?r=1:0)|r
<input type="text" value="1221441" oninput="result.textContent=solution(this.value)" />
<pre id="result"></pre>

user81655
quelle
Schön gemacht. Würden Sie erklären, wie |das in diesem Fall funktioniert?
Pavlo
1
@pavlo Danke. Es ist eine kürzere Schreibweise (x.map(...),v). Es funktioniert, weil das Array, das von der mapRückgabe umgewandelt wird, auf 0und 0|v == v.
user81655
2

Lua , 146 142 108 162 159 149 144 135 132 118 113 Bytes

z,q,s=0,0,io.read()for i in s:gmatch'.'do t=i-z if 2==math.abs(t)or t==q then return''end q=-t z=i end return 2>1

Gibt true oder false bei einer Zahlenfolge zwischen 1 und 4 zurück. (Verarbeitet keine Daten oder Zahlen außerhalb des Bereichs.)

Verfolgt einfach, was die letzte Bewegung war und prüft, ob diese Bewegung eine Umkehrung der letzten Bewegung ist (IE, 121 oder 12221) oder ob die Bewegungsentfernung mehr als möglich ist.

EDIT 1 :

6 Bytes gespeichert. Ich habe vergessen, dass if (int) thentrue zurückgegeben wird, wenn int nicht null ist.

Somit:

if t~=0 then

ändert sich zu:

if t then

Auch durch Restrukturierung ein paar Bytes gespart.

EDIT 2 :

Ich finde das langsam heraus. Ich habe die Dokumentation hier gelesen: http://www.lua.org/pil/ Und eine der nützlicheren Seiten zum Golfen ist http://www.lua.org/pil/3.3.html

Dies ist insbesondere sehr hilfreich:

Wie Kontrollstrukturen betrachten alle logischen Operatoren false und nil als false und alles andere als true.

Dies bedeutet für mich, dass ich meine Deklaration für q ( die ursprünglich auf 0 gesetzt war ) entfernen kann, da sie so lange als "falsch" betrachtet wird, bis sie gesetzt wird. Dadurch spare ich ein paar Bytes mehr.

Eine andere erwähnenswerte Sache, die ich nicht benutze, ist, wenn Sie Werte in Lua tauschen möchten, können Sie einfach a,b=b,a auf eine temporäre Variable verzichten.

EDIT 3

Durch eine clevere Rekonstruktion und eine neue Funktion habe ich den Byte-Countdown um 9 erhöht.

Bester Modus zum Empfangen von Eingaben

Wenn Sie eine Liste mit Zahlen einlesen und nacheinander mit ihnen arbeiten müssen, können Sie Folgendes verwenden:

for x in string:gmatch('.') do
    print(x) --This is our number
end

Im Vergleich zu Ihrer Alternative mit string: sub sehen Sie den Wert für Golf (oder allgemeine Verwendung):

for x=1,string:len() do
    print(string:sub(x,x)) --This is our number
end

Restrukturierungsfunktionen oder Strings

Zweitens, wenn Sie mehrere Deklarationen in einer Zeile haben und einer der Werte eine Funktion ist oder wenn Sie eine Bedingung haben, in der Sie eine Zahl mit dem Ergebnis einer Funktion wie dieser vergleichen:

x,y,z=io.read(),0,0 print('test')

if math.abs(x)==2 then

Wenn Sie es so umstrukturieren, dass die schließenden Klammern das letzte Zeichen in der Bedingung oder Deklaration sind, können Sie ein Zeichen wie das folgende ausschneiden:

y,z,x=0,0,io.read()print('test') --Notice no space

if 2==math.abs(x)then --If we put the '2' first in the conditional statement, we can now remove a space character

Rückgabebedingungen, die True oder False anstelle von 'True' oder 'False' entsprechen

Ich fand einen halb amüsanten Weg, um meinen Byte-Count noch weiter zu reduzieren. Wenn Sie true oder false zurückgeben müssen, können Sie eine Anweisung zurückgeben, die true oder false entspricht und weniger Zeichen als "true" oder "false" enthält.

Vergleichen Sie zum Beispiel:

return true
return false

Zu:

return 2>1
return 1>2
Skyl3r
quelle
121sollte falsch ausgeben.
Lirtosiast
Ah vergiss es. Aha. Wird in Kürze
behoben
Sie könnten daran interessiert sein, einige dieser Lua-Tipps zu den Golf-Tipps in Lua hinzuzufügen, wenn Sie sie dort nicht bereits aufgelistet sehen.
Apsillers
2

MATL, 49 Bytes (nicht konkurrierende 1 )

1. Die Antwort (ab) verwendet die weniger strenge Indizierung neuerer Versionen von MATL und hätte zum Zeitpunkt der Veröffentlichung dieser Herausforderung nicht funktioniert.

dt~aX`tt~f1)q:)w3MQJh)_ht~a]tT-3hX|n2=wT_3hX|n2=+

Probieren Sie es online! .

Ich habe diese Herausforderung beim Best of PPCG 2016 gesehen und festgestellt , dass dies meinen Lieblingsoperator verwenden kann :

d

Oder diffin MATLAB / Octave (ich werde die MATLAB / Octave-Terminologie in meiner Erklärung frei verwenden, da sie für Menschen leichter zu lesen ist). Dieser Befehl berechnet die elementweise Differenz in einem Vektor oder in diesem Fall in einem Zeichenarray.

Für dieses Problem weisen die Unterschiede ein interessantes Muster auf. Beachten Sie, dass

Ein Richtungswechsel muss bedeuten, dass eine Note zweimal gespielt wird .

Für das Differenzmuster (vorerst ohne Berücksichtigung des 1-4Übergangs) bedeutet dies, dass

Bei einer Änderung der Anmeldung diff(input)muss eine ungerade Anzahl von Nullen dazwischen liegen. Umgekehrt darf sich das Vorzeichen nach einer geraden Anzahl von Nullen nicht ändern .


Ich implementierte dies, indem ich für jedes Array die erste Null fand. Ich trimme die Null heraus und multipliziere alle Elemente danach mit -1. Das bedeutet für das Endergebnis, dass alle Elemente müssen das gleiche Vorzeichen haben. Natürlich gibt es das kleine Problem des -3Gleichmachens +1und des 2generellen Verbots. Ich habe das gelöst, indem ich die Mengenvereinigung des Ergebnisses mit genommen [1 -3]und überprüft habe, ob diese Größe 2 hat (dh, keine unzulässigen Elemente sind durch die Vereinigung in die Menge eingegangen). Wiederholen Sie diesen [-1 3]Vorgang für und prüfen Sie, ob einer der beiden (oder beide im Fall einer Eingabe mit einer Länge) wahr ist.

d                                % Difference of input
 t~a                             % Check if any element equals 0
    X`                     t~a]  % Start while loop, ending in the same check
       t~                           % Get a new vector, logical negated to find zeroes.
          f1)                       % Find the position of the first zero. 
      t         q:)                 % Decrement by 1, to index all elements before that zero.
                   w3MQJh)          % Push the result of 'find', but increment to get all elements after.
                         _h         % Multiply the second half by -1, and concatenate horizontally.

  T-3hX|n2=                      % Check if set union with [1 -3] is size 2
 t        wT_3hX|n2=             % Check if set union with [-1 3] is size 2
                    +            % Logical OR. 
Sanchises
quelle
@ LuisMendo Danke. Ich muss wirklich nachlesen M, das letzte Mal, als ich es ausprobiert habe, hat es anders funktioniert als erwartet, also habe ich es vorerst einfach ignoriert. Ist es richtig zu sagen, dass es sein muss, 3Mweil ich dann die Eingabe von not ), not :but of q(Überspringen, wda es keine normale Funktion ist) bekomme ?
Sanchises
Ja genau. wwird übersprungen, da dies keine normale Funktion ist. Normale Funktionen, die keine Eingaben benötigen, werden ebenfalls übersprungen
Luis Mendo
2

Python (3.5) 160 151 150 Bytes

Eine rekursive Lösung

def f(s):g=lambda s,c:s==''or g(s[1:],(c[:4]*2)[(s[0]==c[0])*2+1:])if s==''or s[0]in c[:2]else 0;return any([g(s,"1234123"[i:])for i in range(4)])

Ungolfed ohne Lambda

def f(s):
    def g(s,c):
        if s=='' or s[0] in c[:2] :
            return s=='' or g(s[1:],(c[:4]*2)[(s[0]==c[0])*2+1:])
        else:
            return False
    return any([g(s,"1234123"[i:]) for i in range(4)])

Ich drehe den ganzen Kasten anstelle der Kurbel. Die Kurbelposition liegt zwischen dem ersten und dem zweiten Zeichen der c-Zeichenfolge. Ich muss alle Startpositionen der Kurbel testen.

Trick verwenden, um die Saite zu drehen

Die übliche Art, einen String in python ( s[i:]+s[:i]) zu drehen, muss sowohl index als auch string wiederholen. In diesem Fall dupliziere ich die Zeichenfolge und schneide die ersten Zeichen ab.

(c*2)                        # duplicate the string
     [(s[0]==c[0])*2+1       # test that return 1 if firsts characters match 3 instead 
                      :]     
                        [:4] # crop again to have a 4 characters string

Testfälle

[f(i) for i in ["1", "1234", "1221", "3333", "143332", "22234", "2234", "22214", "1221441", "41233", "13", "1224", "121", "12221", "43221"]]
[True, True, True, True, True, True, True, True, True, True, False, False, False, False, False]
Erwan
quelle
1
Sie können das Leerzeichen bei entfernen 3"[i:]) for.
Erik der Outgolfer
@EriktheOutgolfer danke ich entferne es.
Erwan
1

JavaScript (ES2015), 110 95

p=(s,d)=>(h=s[0],t=s.slice(1),g=t[0],!g||(d?g==h?p(t,-d):g%4==(h-d)%4&&p(t,d):p(s,1)||p(s,-1)))

15 Bytes von Neil gespeichert! Originalversion ungolfed:

p = (s, d) => {
  h = s[0]
  t = s.substr(1)

  if (!t[0]) return true
  if (!d) return p(s, 1) || p(s, -1)
  if (t[0] == h) return p(t, d*-1)
  if (t[0] == (h-d > 4 ? 1 : h-d || 4)) return p(t, d)

  return false
}

Tests: https://jsbin.com/cuqicajuko/1/edit?js,console

Pavlo
quelle
1
Sie 17 Bytes gespeichert:(s,d)=>(h=s[0],t=s.slice(1),g=t[0],!g||(d?g==h?p(t,-d):g%4==(h-d)%4&&p(t,d):p(s,1)||p(s,-1)))
Neil
Immer noch nicht so kurz wie die Antwort von @ user81655.
Neil
1

Turing-Maschinencode, 395 Bytes

0 1 _ r a
0 2 _ r b
0 3 _ r c
0 4 _ r d
a 1 _ r a
a 2 _ r E
a 3 _ r h
a 4 _ r S
b 1 _ r W
b 2 _ r b
b 3 _ r S
b 4 _ r h
c 1 _ r h
c 2 _ r N
c 3 _ r c
c 4 _ r W
d 1 _ r N
d 2 _ r h
d 3 _ r E
d 4 _ r d
N 1 _ r W
N 2 _ r E
N _ _ r r
N * _ r h
E 2 _ r N
E 3 _ r S
E _ _ r r
E * _ r h
S 3 _ r E
S 4 _ r W
S _ _ r r
S * _ r h
W 4 _ r S
W 1 _ r N
W _ _ r r
W * _ r h
h _ 0 r halt
h * _ r h
r _ 1 r halt

Probieren Sie es online!

Dies ist im Grunde ein staatlicher Ansatz:

  • Der Ausgangszustand ist 0.
  • a, b, c, Und dist „unentschieden states“ , die erst am Anfang auftreten
  • N, E, S, Und Wsind die "beschlossen Staaten", offenbar für stehende North, East, South und West.
Undichte Nonne
quelle
1

Thue, 203 Bytes

Ich kann mir nicht vorstellen, wie ich weiter Golf spielen kann.

0::=:::
>11::=>1
>22::=>2
>33::=>3
>44::=>4
>12::=b
>21::=d
>14::=c
>41::=a
>23::=c
>32::=a
>34::=d
>43::=b
a1::=d
a2::=b
b2::=a
b3::=c
c3::=b
c4::=d
d4::=c
d1::=a
a<::=~n
b<::=~e
c<::=~s
d<::=~w
::=
>0<

Wenn die Notenfolge möglich ist, wird die Endrichtung ausgegeben, andernfalls ist die Ausgabe leer.

MegaTom
quelle
1

Prolog (SWI) , 117 Bytes

a(N,P):-P=N;N=1,P=4,!;P is N-1.
m([A,B|C],[X,Y|Z]):-a(A,X),a(B,X),a(B,Y),X\=Y,m([B|C],[Y|Z]).
m([_],_).
p(N):-m(N,_).

Definiert ein Prädikat p, das bei abspielbaren Eingaben (als Liste von Ganzzahlen angegeben) erfolgreich ist und bei nicht abspielbaren Eingaben fehlschlägt. Probieren Sie es online!

Erläuterung

aDefiniert eine Nachbarschaftsbeziehung zwischen Note Nund Kurbelposition P. Wir definieren die Position p zwischen den Noten p und p + 1 . Somit ist eine Position benachbart zu notieren Niff

  • es ist gleich N( P=N); oder
  • die Note ist 1 und die Position ist 4 ( N=1,P=4); oder
  • Der obige Fall ist nicht wahr ( !) und die Position ist gleich N-1( P is N-1).

mNimmt eine Liste von Noten und versucht, eine Liste von Positionen zu generieren, die diese Noten spielen. AWird die Note gerade gespielt? Wird die Note gerade gespielt B? Xist die aktuelle Kurbelposition, Yist die nächste Kurbelposition. Ein Zug ist gültig, wenn

  • Die gerade gespielte Note befindet sich neben der aktuellen Kurbelposition ( a(A,X)).
  • Die zu spielende Note befindet sich ebenfalls neben der aktuellen Kurbelposition ( a(B,X)).
  • Die zu spielende Note befindet sich neben der nächsten Kurbelposition ( a(B,Y)). und
  • Die beiden Kurbelpositionen sind nicht gleich ( X\=Y).

Wenn all dies zutrifft, rekursieren Sie. Wenn wir eine Note erfolgreich gefunden haben ( m([_],_)), kann die Notenfolge abgespielt werden.

Für diese Frage ist es uns nur wichtig, ob eine Abfolge von Bewegungen vorhanden ist. Daher definieren wir, dass die generierte Liste der Kurbelpositionen paufgerufen mund verworfen wird.

Sehen Sie eine ungolfed Version und überprüfen Sie alle Testfälle hier .

DLosc
quelle