Czy moja 4-nutowa pozytywka może odtworzyć tę piosenkę?


51

Mam sterowaną korbą pozytywkę, która może odtwarzać serię czterech dźwięków. Kiedy obracam korbą, wyrywa ona jeden z czterech strun, w zależności od położenia korby i kierunku obrotu. Kiedy korba jest skierowana na północ, skrzynia (z jej łańcuchami ponumerowanymi od 1 do 4) wygląda następująco:

1  |  2
   |
   O   

4     3

Stamtąd mogę obrócić korbą w kierunku zgodnym z ruchem wskazówek zegara, aby zerwać sznur nr 2 i skierować korbę na wschód:

1     2

   O---   

4     3

Alternatywnie, mógłbym również obrócić korbą w kierunku przeciwnym do ruchu wskazówek zegara z północy, aby zagrać na strunie nr 1 i zakończyć korbą skierowaną na zachód:

1     2

---O   

4     3

Zatem w danym momencie skrzynka może odtwarzać jedną z dwóch nut: następną nutę dostępną w kierunku zgodnym z ruchem wskazówek zegara lub następną nutę w kierunku przeciwnym do ruchu wskazówek zegara.

Wyzwanie

Twoim wyzwaniem jest, aby napisać program lub funkcję, która akceptuje niepusty ciąg wartości Note (tj cyframi 1pośrednictwem 4) i określić, czy jest to możliwe, aby zagrać tę sekwencję nut na polu muzycznym. Podaj wynik zgodny z prawdą lub fałszem, aby wskazać grywalność lub brak możliwości gry na danych wejściowych.

Niektóre uwagi:

  • Dane wejściowe nie zakładają początkowej pozycji początkowej. Dane wejściowe 214(rozpoczynające się na wschód i poruszające się ściśle przeciwnie do ruchu wskazówek zegara) i 234(rozpoczynające się na północ i poruszające się ściśle zgodnie z ruchem wskazówek zegara) i oba są ważne.

  • Korba może się swobodnie poruszać w dowolnym kierunku po każdej nucie. Seria tej samej nuty jest możliwa (np. 33333) Poprzez przesuwanie się w przód i w tył po jednym strunie. Serię 1221441można doskonale grać (zaczynając na zachód, przesuwając dwa kroki zgodnie z ruchem wskazówek zegara, następnie trzy kroki przeciwnie do ruchu wskazówek zegara, a następnie dwa kroki zgodnie z ruchem wskazówek zegara).

Próbki

Niektóre trueprzypadki:

1
1234
1221
3333
143332
22234
2234
22214
1221441
41233

Niektóre falseprzypadki:

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  

Czy dane wejściowe mogą być ciągiem zawierającym cudzysłowy?
Luis Mendo,

@LuisMendo Jasne, pozwolę na to - jestem zainteresowany twoim algorytmem, nie zmuszając cię do przeskakiwania przez obręcze w celu uzyskania danych wejściowych. W każdym razie istnieje nieoficjalna zgoda społeczności, że ogólnie jest w porządku: Dane wejściowe z lub bez „”?
apsillers

1
Nie wiedziałem tego Dzięki za link!
Luis Mendo,

1
@AJMansfield Nie, rozwiązania powinny pozwolić na dowolnie wiele cykli. Oczywiście, jeśli niektóre dane wejściowe spowodują, że Twój kod przekroczy limit w tłumaczeniu twojego języka lub pamięci komputera, to jest w porządku (ponieważ jest on ograniczony jedynie ilością pamięci, którą fizycznie posiadasz lub twój tłumacz pozwala), ale twoje rozwiązanie nie powinno nakładać dodatkowych ograniczeń jak daleko lub ile razy porusza się korba.
apsillers

1
To wyzwanie wygrało kategorię Nie tak proste, jak się wydaje w Best of PPCG 2016. Niestety, nie możemy dać nagrody za wyzwania, ale Zgarb napisał wyzwanie na twoją cześć . Gratulacje!
Martin Ender

Odpowiedzi:


9

Pyth, 30 27 bajtów

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

Oto pomysł:

 1.5  1  0.5

  2       0

 2.5  3  3.5

Korba jest zawsze w pozycji połowy liczby całkowitej c. Na każdym kroku odzwierciedlamy ją nad nutą pozycji całkowitej nprzez ustawienie c = 2*n-c. Jeśli njest poprawny, czmienia się o ± 1 mod 8. Jeśli njest nieważny, czmienia się o ± 3 mod 8. Łącznie zmniejszamy wartość wejściową, aby zebrać wszystkie wartości c, a następnie sprawdzić, czy wszystkie nuty są prawidłowe. Robimy to dla każdej wartości początkowej c, ponieważ jest krótsza niż sprawdzenie tylko tych sąsiadujących z pierwszą nutą.

Sformatowany:

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

Zestaw testowy .


18

CJam, 34 31 bajtów

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

Zrobiłem to na moim telefonie, więc będę musiał wyjaśnić później. Dane wyjściowe są niepuste, jeśli są zgodne z prawdą.

Wypróbuj online | Zestaw testowy

Wyjaśnienie

Nowy kod nieco zmienia układ:

2    3    4

1    .    5

0/8  7    6

Liczby parzyste odpowiadają pozycjom strun, a liczby nieparzyste odpowiadają pozycjom korby.

Oto co się dzieje:

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

Stos jest następnie automatycznie drukowany na końcu. Wszelkie możliwe pozycje końcowe będą na wyjściu, np. Dla wejścia 1jest wyjście 31, co oznacza, że ​​korba może kończyć się skierowaną w lewo lub w górę.

Gdyby tylko CJam miał filtr z dodatkowym parametrem ...


Edycja: Tymczasowo się wycofuję, a ja przekonuję się, że ten 29-bajtowy działa:

8,q{~2*f{_@-_7b1#@@+8,=|}W-}/

37
Za każdym razem, gdy ktoś odpowiada jakimś trudnym językiem, takim jak cjam, i mówi: „Zrobiłem to na telefonie”, umieram trochę w środku
Dennis van Gils

2
Prawdopodobnie miał na myśli, że tekst został wydrukowany za pomocą telefonu, ale zrobiono to w jego głowie.
Nelson

7

Haskell, 93 88 87 bajtów

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

To ocenia na anonimową funkcję, która pobiera ciąg znaków i zwraca wartość logiczną. Zestaw testowy tutaj.

Wyjaśnienie

Chodzi o to, że lambda po prawej mapuje liczbę ado [[a,a+1],[a+1,a]], dwóch możliwych „ruchów”, które odbywają korbą nad tym numerem, zgodnie z następującym schematem:

  1 (2) 2

(1/5)  (3)

  4 (4) 3

W głównej funkcji anonimowej najpierw robimy mapM((...).read.pure), która konwertuje każdy znak na liczbę całkowitą, stosuje do niego powyższą lambdę i wybiera jeden z dwóch ruchów, zwracając listę wszystkich wynikowych sekwencji ruchów. Następnie sprawdzamy, czy którakolwiek z tych sekwencji ma właściwość, że druga liczba każdego ruchu jest równa pierwszej liczbie następnego modułu 4, co oznacza, że ​​jest to fizycznie możliwa sekwencja. Aby to zrobić, zipkażdy z nich przesuwa sekwencję razem z nią tail, sprawdzamy warunek dla allpar i sprawdzamy, czy anysekwencja się sprawdza True.



6

Siatkówka , 127 109 bajtów

^((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))*$

To drukuje 0lub 1odpowiednio.

Wypróbuj online! (Jest to nieco zmodyfikowana wersja, która oznacza wszystkie dopasowania na wejściu zamiast drukowania 0lub 1.)

Próbowałem wymyślić elegancki algorytm, ale moich pierwszych kilku próbom nie udało się ominąć cofania się ... a implementacja powrotu jest denerwująca ... więc użyłem języka, który wykonuje dla mnie cofanie, w którym muszę tylko zakodować prawidłowe rozwiązanie. Niestety kodowanie jest dość pełne i dość zbędne ... Jestem pewien, że można to skrócić.

Podczas gdy próbuję wymyślić coś bardziej zgrabnego, jeśli ktoś chce dowiedzieć się, jak to działa, oto nieco bardziej czytelna wersja:

^
(
    (?<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)
)*
$

A oto wskazówka:

1  a  2

d  O  b

4  c  3

6

MATL , 57 55 bajtów

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

Używa bieżącej wersji (10.2.1) , która jest wcześniejsza niż to wyzwanie.

EDIT (17 stycznia 2017): ze względu na zmiany w języku,v musi być zastąpiona &v, a tL3$)przez Y)(dodatkowo kilka innych usprawnień mogły być wykonane). Poniższy link zawiera te dwie modyfikacje

Wypróbuj online!

Wyjaśnienie

Jest to oparte na dwóch moich ulubionych narzędziach do gry w golfa kodowego: brutalnej sile i konwolucji .

Kod określa ścieżkę , po której następuje korby pod względem współrzędnych 0.5, 1.5itd Każdy numer mówi położenia wału korbowego pomiędzy nutami. Kod najpierw tworzy tablicę ścieżek ze wszystkimi możliwymi ścieżkami, które zaczynają się od pierwszej nuty ciągu wejściowego. Każda ścieżka jest kolumną w tej tablicy. To składnik siły brutalnej .

Z tej tablicy ścieżek uzyskuje się tablicę nut , gdzie każda kolumna jest możliwą do wykonania sekwencją granych nut. Na przykład ruch z pozycji 0.5do 1.5produkowania nuty 1. Polega to na przyjęciu średniej między pozycjami, a następnie zastosowaniu operacji modulo 4. Średnia bieżąca wzdłuż każdej kolumny jest wykonywana za pomocą splotu 2D .

Na koniec program sprawdza, czy jakakolwiek kolumna tablicy nut pokrywa się z danymi wejściowymi.

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

5

Pyth, 43

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

Pakiet testowy

Jest to prawdopodobnie bardzo gra w golfa, a także nie jest to optymalny algorytm do gry w golfa (spodziewam się, że wyliczenie wszystkich ścieżek będzie krótsze?) ... W każdym razie, jeśli znajdziesz jakiś błąd w algorytmie, daj mi znać, myślę, że powinien działać, ale ja wcześniej się myliłem!

Wyjaśnię mój algorytm, używając przykładowego wejścia 1221. Program ten pierwszy odwzorowuje cyfry przed ich następców, tak: [[1,2],[2,2],[2,1]]. Potem robi się ich różnic mod 4(Pyth dostaje wynik odpowiadający znak prawego argumentu %, więc jest zawsze dodatnia) [3,0,1]. Następnie wyniki są podzielone na 0i nie 2odejmuje się od każdego z nich [[1],[-1]].

Teraz, gdy konfiguracja jest zakończona, tworzymy listę [-1,1,-1...]i jej negację [1,-1,...], obie o tej samej długości co tablica wynikowa z wcześniej. Następnie dla każdej z tych list wykonaj odejmowanie zgodnie z ustaleniami między elementami listy i listą wygenerowaną we wcześniejszym kroku. Następnie, jeśli którykolwiek z wyników zawiera tylko puste listy, generujemy true.


Co rozumiesz przez „wyniki są podzielone na 0”? W szczególności, co można dostać za 1221221a 1221441?
Neil

1
@ Neil 1221221jest fałszem i 1221441ogólnie daje prawdę, ale jeśli rozumiem, że chcesz uzyskać wynik po tym kroku w algorytmie? W takim przypadku daje to: od [3, 0, 1, 3, 0, 1]do [[3], [1, 3], [1]]i [3, 0, 1, 1, 0, 3]do [[3], [1, 1], [3]]. Daj mi znać, jeśli chcesz wyjaśnić coś innego :)
FryAmTheEggman

Myślę, że jestem bardziej zdezorientowany niż wcześniej, więc czy mógłbyś dokończyć te dwa przykłady, aby wyjaśnić, w jaki sposób osiąga się (prawidłowe) wyniki?
Neil

1
@Neil Pewnie, nie ma problemu :) Następnie odejmujemy, aby uzyskać: [[1], [-1, 1], [-1]]i [[1], [-1, -1], [1]]stąd widać, że pierwsza nie ma list, które zmieniają się na przemian -1i 1podczas gdy druga lista, co daje końcowy wynik. Algorytm jest nieco tępy, ale zasadniczo odwzorowuje zmiany kierunku 0i kierunek +/-1, a następnie sprawdza, czy nie są wykonywane żadne skoki i czy kierunki mają sens.
FryAmTheEggman

Och, więc brakowało mi trochę tego, że każda lista podziału musi składać się z tej samej wartości, a te wartości muszą się zmieniać. Dzięki!
Neil

4

Matlab, 279 180 bajtów

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

Całkiem leniwe rozwiązanie, ale najkrótsze, jakie udało mi się wymyślić. Stworzyłem specjalną matrycę: kiedy kodujesz stan skubaka i ostatni ciąg, który ma być skubany, zwraca wektor, który koduje nową pozycję skubaka i czy poprzedni skubanie było w ogóle możliwe. Teraz po prostu zapętlamy wszystkie nuty z dwóch możliwych pozycji początkowych i sprawdzamy, czy jedna z nich daje odtwarzalną melodię. Prawdopodobnie można grać w golfa o wiele więcej.

Rozszerzone i wyjaśnione źródło:

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

4

ES6, 104 100 bajtów

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"))

Edycja: Zapisano 4 bajty dzięki @DigitalTrauma.

To jest kompletne przepisanie, ponieważ moje poprzednie podejście było wadliwe.

Zaczynam od zredukowania wszystkich serii cyfr do 1 lub 2 w zależności od tego, czy w serii była liczba nieparzysta czy parzysta. Następnie szukam wszystkich nielegalnych kombinacji:

  • 13|24|31|42 (przeciwne strony)
  • 3[24]{2}1jak 3221i 3441są nielegalne
  • podobnie do 4xx2, 1xx3i 2xx4gdzie xjest albo brakujących cyfr
  • (.).\1ponieważ rzeczy takie 121są nielegalne ( 111zostały zredukowane do 1wcześniejszych)

Jeśli nie ma nielegalnych par lub „potrójnych”, to cały ciąg jest legalny (dowód przez indukcję pozostawia się jako ćwiczenie, ponieważ tutaj jest późna noc).

Starałem się uprościć, 3[24]{2}1|1[24]{2}3stosując negatywne stwierdzenie z wyprzedzeniem, ale okazało się, że tak jest dłużej.


f("1122") => true@DigitalTrauma
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Nie widzę w tym nic złego. Z drugiej strony zdałem sobie sprawę, że to f("1221221")wychodzi zła odpowiedź, więc będę musiał przemyśleć.
Neil

Jest to sprecyzowane miło to zestaw testów, '43221' nie powiedzie się: jsbin.com/vafitotequ/1/edit?js,console
Pavlo

@Pavlo Ups, ja grałem [24][24]na (2|4)\1ale nie przetestowane odpowiednio. Przepraszam za to.
Neil

Czy potrafisz grać [24][24]w golfa [24]{2}?
Digital Trauma

2

JavaScript (ES6), 80 bajtów

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

Wyjaśnienie

i%4 jest bieżącą pozycją korby:

    1 (i%4 == 1) 2   

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

    4 (i%4 == 3) 3   

Wcięte i komentowane

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

Test

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>


Ładnie wykonane. Czy wyjaśniłbyś, jak |działa w tym przypadku?
Pavlo

1
@pavlo Dzięki. To krótszy sposób pisania (x.map(...),v). Działa, ponieważ tablica, do której mapzwracane są dane rzutowane na 0i 0|v == v.
user81655

2

Lua , 146 142 108 162 159 149 144 135 132 118 113 113 bajtów

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

Zwraca wartość true lub false, biorąc pod uwagę ciąg liczb od 1 do 4. (Nie obsługuje danych ani numerów spoza zakresu.

Po prostu śledzi, jaki był ostatni ruch i sprawdza, czy ruch ten jest odwrotnością ostatniego ruchu (IE, 121 lub 12221), czy też odległość ruchu jest większa niż to możliwe.

EDYCJA 1 :

Zapisano 6 bajtów. Zapomniałem, że if (int) thenzwraca true, jeśli int jest niezerowe.

A zatem:

if t~=0 then

zmiany w:

if t then

Oszczędzono także kilka bajtów poprzez restrukturyzację.

EDYCJA 2 :

Powoli to rozgryzam. Przeczytałem tutaj dokumentację: http://www.lua.org/pil/ A jedną z bardziej przydatnych stron do gry w golfa jest http://www.lua.org/pil/3.3.html

Jest to szczególnie pomocne:

Podobnie jak struktury kontrolne, wszystkie operatory logiczne uznają fałsz i zero za fałszywe, a wszystko inne za prawdziwe.

Dla mnie oznacza to, że mogę iść dalej i usunąć moją deklarację dla q ( która początkowo była ustawiona na 0 ), ponieważ będzie ona uważana za „fałszywą”, dopóki nie zostanie ustawiona. Dzięki temu oszczędzam jeszcze kilka bajtów.

Inną rzeczą, o której warto wspomnieć, chociaż jej nie używam, jest to, że jeśli chcesz zamienić wartości w Lua, możesz po prostu zrezygnować a,b=b,az potrzeby tymczasowej zmiennej.

EDYCJA 3

Tak więc, dzięki sprytnej rekonstrukcji, a także nowej funkcji, odliczam bajt o 9 więcej.

Najlepszy tryb do odbierania danych wejściowych

Jeśli chcesz czytać listę numerów i wykonywać na nich operacje pojedynczo, możesz użyć:

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

W porównaniu do alternatywy wykorzystującej string: sub, możesz zobaczyć wartość golfa (lub ogólnego zastosowania):

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

Restrukturyzacja funkcji lub ciągów

Po drugie, jeśli masz wiele deklaracji w jednym wierszu, a jedna z wartości jest funkcją lub masz warunek, w którym porównujesz liczbę z wynikiem funkcji takiej jak te:

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

if math.abs(x)==2 then

przekształcając go tak, aby nawias zamykający był ostatnim znakiem warunku lub deklaracji, możesz wyciąć znak taki:

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

Zwracane warunki, które odpowiadają prawdzie lub fałszowi zamiast „prawdy” lub „fałszu”

Znalazłem na poły zabawny sposób, aby jeszcze bardziej zmniejszyć liczbę moich bajtów. Jeśli musisz zwrócić wartość prawda lub fałsz, możesz zwrócić instrukcję, która jest równa prawdzie lub fałszowi, która ma mniej znaków niż same „prawda” lub „fałsz”.

Na przykład porównaj:

return true
return false

Do:

return 2>1
return 1>2

121powinien wypisać wartość false.
lirtosiast

Ah nie ważne. Widzę. Naprawimy wkrótce
Skyl3r

Możesz być zainteresowany dodaniem niektórych z porad Lua do Porad dotyczących gry w golfa w Lua, jeśli jeszcze ich tam nie ma na liście.
apsillers

2

MATL, 49 bajtów (niekonkurencyjny 1 )

1. Odpowiedź (ab) wykorzystuje mniej ścisłe indeksowanie nowszych wersji MATL i nie działałaby w chwili opublikowania tego wyzwania.

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

Wypróbuj online! .

Widziałem to wyzwanie podczas Best of PPCG 2016 i pomyślałem, że może to wykorzystać mój ulubiony operator :

d

Lub diffw MATLAB / Octave (swobodnie będę używać terminologii MATLAB / Octave w moim objaśnieniu, ponieważ dla ludzi jest łatwiejszy do odczytania). To polecenie oblicza różnicę elementarną w wektorze lub, w tym przypadku, w tablicy znaków.

W przypadku tego problemu różnice wykazują ciekawy wzór. Zauważ, że

Zmiana kierunku musi oznaczać, że nuta jest odtwarzana dwukrotnie .

Dla wzorca różnicy (na razie ignorując 1-4przejście) oznacza to, że

Zmiana w logowaniu diff(input)musi zawierać nieparzystą liczbę zer. I odwrotnie, znak nie może się zmieniać po parzystej liczbie zer.


Zaimplementowałem to, znajdując pierwsze zero dla każdej tablicy. Wycinam zero i mnożę wszystkie elementy po nim -1. Dla wyniku końcowego oznacza to, że wszystkie elementy muszą mieć ten sam znak. Oczywiście istnieje niewielka kwestia -3wyrównywania +1i 2ogólnie bycia niedozwolonym. Rozwiązałem to, biorąc zestaw sumy wyniku [1 -3]i sprawdzając, czy ma ona rozmiar 2 (tj. Żadne niedozwolone elementy nie „weszły” do zestawu przez łączenie). Powtórz dla [-1 3]i sprawdź, czy którykolwiek (lub oba, w przypadku danych wejściowych o długości 1) jest prawdziwy.

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. 

@LuisMendo Thanks. Naprawdę muszę przeczytać M, kiedy ostatnio próbowałem, zadziałało inaczej niż oczekiwano, więc na razie zignorowałem to. Czy słusznie jest powiedzieć, że tak musi być, 3Mponieważ wtedy dostaję wejście nie ), nie :ale q(pomijanie, wponieważ nie jest to normalna funkcja)?
Sanchises,

Tak, dokładnie. wjest pomijany, ponieważ nie jest to normalna funkcja. Normalne funkcje, które nie wymagają wprowadzania danych, również zostałyby pominięte
Luis Mendo,

2

Python (3.5) 160 151 150 bajtów

Rozwiązanie rekurencyjne

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

Bez golfa bez 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)])

Obracam wszystkie pudła zamiast korby. Pozycja korby znajduje się między pierwszym a drugim znakiem łańcucha c. Muszę przetestować całą początkową pozycję korby.

Sztuczka służy do obracania sznurka

Zwykły sposób obracania łańcucha w python ( s[i:]+s[:i]) również wymaga powtórzenia zarówno indeksu, jak i łańcucha. W takim przypadku powielam ciąg i kadruję pierwsze znaki.

(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

Przypadki testowe

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

1
Możesz usunąć miejsce na 3"[i:]) for.
Erik the Outgolfer

@EriktheOutgolfer dzięki, że go usunęłem.
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 bajtów zapisanych przez Neila! Oryginalna wersja bez golfa:

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
}

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


1
Zapisałem ci 17 bajtów:(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

Nadal jednak nie jest tak krótki, jak odpowiedź @ user81655.
Neil

1

Kod maszynowy Turinga, 395 bajtów

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

Wypróbuj online!

Jest to w zasadzie podejście państwowe:

  • Stan początkowy to 0.
  • a, b, c, I dsą „stany niezdecydowanych”, które występują tylko na początku
  • N, E, S, I Wsą "postanowił członkowskimi", oczywiście stojąc na NPółnocy, East, SOUtH i West.

1

Czw. 203 bajty

Nie mogę wymyślić, jak grać w golfa dalej.

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<

Jeśli sekwencja nut jest możliwa, wyświetli kierunek zakończenia, w przeciwnym razie wyjście będzie puste.


1

Prolog (SWI) , 117 bajtów

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,_).

Definiuje predykat, pktóry odnosi sukces na wejściach możliwych do gry (podanych jako lista liczb całkowitych), a na wejściach niemożliwych do odtworzenia. Wypróbuj online!

Wyjaśnienie

aokreśla relację sąsiedztwa między nutą Na położeniem korby P. Definiujemy pozycję p, która będzie pomiędzy nutami p i p + 1 . Zatem pozycja sąsiaduje z nutą Niff

  • jest równe N( P=N); lub
  • nuta to 1, a pozycja to 4 ( N=1,P=4); lub
  • powyższy przypadek nie jest prawdziwy ( !), a pozycja równa się N-1( P is N-1).

mbierze listę nut i próbuje wygenerować listę pozycji, które będą odtwarzać te nuty. Ato właśnie zagrana nuta, Bto nuta, która ma zostać odtworzona; Xto bieżąca pozycja korby, Yto następna pozycja korby. Ruch jest ważny iff

  • właśnie zagrana nuta sąsiaduje z bieżącą pozycją korby ( a(A,X));
  • nuta, która ma zostać odtworzona, sąsiaduje również z bieżącą pozycją korby ( a(B,X));
  • nuta, która ma zostać odtworzona, sąsiaduje z następną pozycją korby ( a(B,Y)); i
  • dwie pozycje korby nie są równe ( X\=Y).

Jeśli wszystkie z nich się utrzymują, powtórz. Jeśli uda nam się przejść do jednej nuty ( m([_],_)), sekwencję nut można zagrać.

W przypadku tego pytania zależy nam tylko na tym, czy istnieje sekwencja ruchów, dlatego definiujemy, paby wywoływać mi odrzucać wygenerowaną listę pozycji korby.

Zobaczyć ungolfed wersji i zweryfikować wszystkie przypadki testowe tutaj .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.