Lisp Extraktionsmission

19

In Sprachen im Lisp-Stil wird eine Liste normalerweise folgendermaßen definiert:

(list 1 2 3)

Für die Zwecke dieser Herausforderung enthalten alle Listen nur positive ganze Zahlen oder andere Listen. Wir lassen das listSchlüsselwort auch am Anfang weg , daher sieht die Liste jetzt so aus:

(1 2 3)

Wir können das erste Element einer Liste erhalten, indem wir verwenden car. Beispielsweise:

(car (1 2 3))
==> 1

Und wir können die ursprüngliche Liste mit dem ersten Element erhalten, das mit entfernt wird cdr:

(cdr (1 2 3))
==> (2 3)

Wichtig: cdrGibt immer eine Liste zurück, auch wenn diese Liste ein einzelnes Element enthalten würde:

(cdr (1 2))
==> (2)
(car (cdr (1 2)))
==> 2

Listen können sich auch in anderen Listen befinden:

(cdr (1 2 3 (4 5 6)))
==> (2 3 (4 5 6))

Schreiben Sie ein Programm, das Code zurückgibt, der eine bestimmte Ganzzahl in einer Liste verwendet carund zurückgibt cdr. In dem Code, den Ihr Programm zurückgibt, können Sie davon ausgehen, dass die Liste gespeichert ist l, dass sich die Ziel-Ganzzahl lirgendwo befindet und dass alle Ganzzahlen eindeutig sind.

Beispiele:

Eingang: (6 1 3) 3

Ausgabe: (car (cdr (cdr l)))

Eingang: (4 5 (1 2 (7) 9 (10 8 14))) 8

Ausgabe: (car (cdr (car (cdr (cdr (cdr (cdr (car (cdr (cdr l))))))))))

Eingang: (1 12 1992) 1

Ausgabe: (car l)

Absinth
quelle
Können wir zuerst die ganze Zahl und dann die Liste eingeben?
Martin Ender
@ MartinBüttner Klar.
Absinth
Was ist mit (1 2 3) 16, sollen wir zurückkehren ()?
Coredump
@coredump Gute Frage. Sie können davon ausgehen, dass die Ziel-Ganzzahl immer im Ausdruck enthalten ist, sodass ein Fall wie (1 2 3) 16dieser niemals angezeigt wird.
Absinth
Können wir zwei Eingaben erhalten, eine für die Liste und eine für die ganze Zahl?
Blackhole

Antworten:

1

CJam, 59

q"()""[]"er~{:AL>{0jA1<e_-_A(?j'l/"(car l)"@{2'dt}&*}"l"?}j

Probieren Sie es online aus

Erläuterung:

q                 read the input
"()""[]"er        replace parentheses with square brackets
~                 evaluate the string, pushing an array and a number
{…}j              calculate with memoized recursion using the array as the argument
                   and the number as the memozied value for argument 0
  :A              store the argument in A
  L>              practically, check if A is an array
                   if A is a (non-empty) array, compare with an empty array
                   (result 1, true)
                   if A is a number, slice the empty array from that position
                   (result [], false)
    {…}           if A is an array
      0j          get the memoized value for 0 (the number to search)
      A1<         slice A keeping only its first element
      e_          flatten array
      -           set difference - true iff the number was not in the array
      _           duplicate the result (this is the car/cdr indicator)
      A(          uncons A from left, resulting in the "cdr" followed by the "car"
      ?           choose the cdr if the number was not in the flattened first item,
                   else choose the car
      j           call the block recursively with the chosen value as the argument
      'l/         split the result around the 'l' character
      "(car l)"   push this string
      @           bring up the car/cdr indicator
      {…}&        if true (indicating cdr)
        2'dt      set the character in position 2 to 'd'
      *           join the split pieces using the resulting string as a separator
    "l"           else (if A is not an array) just push "l"
                   (we know that when we get to a number, it is the right number)
    ?             end if
aditsu
quelle
10

Common Lisp, 99

Die folgende 99-Byte-Lösung ist eine CL-Version der Nizza- Schema-Antwort .

(defun g(l n &optional(o'l))(if(eql n l)o(and(consp l)(or(g(car l)n`(car,o))(g(cdr l)n`(cdr,o))))))

Ich habe ursprünglich versucht, positionund zu verwenden position-if, aber es stellte sich heraus, dass es nicht so kompakt war, wie ich es gerne gehabt hätte (209 Bytes):

(lambda(L x &aux(p'l))(labels((f(S &aux e)(cons(or(position x S)(position-if(lambda(y)(if(consp y)(setf e(f y))))S)(return-from f()))e)))(dolist(o(print(f L))p)(dotimes(i o)(setf p`(cdr,p)))(setf p`(car,p)))))

Erweitert

(lambda
  (l x &aux (p 'l))
  (labels ((f (s &aux e)
             (cons
              (or (position x s)
                  (position-if
                   (lambda (y)
                     (if (consp y)
                         (setf e (f y))))
                   s)
                  (return-from f nil))
              e)))
    (dolist (o (print (f l)) p)
      (dotimes (i o) (setf p `(cdr ,p)))
      (setf p `(car ,p)))))

Beispiel

(funcall *fun* '(4 5 (1 2 (7) 9 (10 8 14))) 14)

Die Liste ist zitiert, aber wenn Sie wirklich wollen, kann ich ein Makro verwenden. Der zurückgegebene Wert ist [1] :

(CAR (CDR (CDR (CAR (CDR (CDR (CDR (CDR (CAR (CDR (CDR L)))))))))))

Für Tests habe ich eine Lambda-Form generiert, bei der les sich um eine Variable handelte:

(LAMBDA (#:G854) (CAR (CDR (CDR (CAR (CDR (CDR (CDR (CDR (CAR (CDR (CDR #:G854))))))))))))

Wenn Sie dies mit der ursprünglichen Liste aufrufen, wird 14 zurückgegeben.


[1] (caddar (cddddr (caddr l)))wäre auch nett

Core-Dump
quelle
2
Du hast eine Frage zu Lisp mit Lisp beantwortet ! Es ist Lisp-ception!
DanTheMan
4
@DanTheMan Lisp-ception ist so ziemlich das, was Lisp definiert ;-)
Coredump
9

Retina , 170 142 125 115 114 87 84 83 75 73 70 69 68 67 Bytes

Ja, weniger als 50% von mehr als 100 Bytes aus meinem ersten Versuch. :)

\b(.+)\b.* \1$
(
^.
l
\(
a
+`a *\)|\d


d
+`(.*[l)])(\w)
(c$2r $1)

Verwenden Sie das -sFlag, um den Code aus einer einzelnen Datei auszuführen .

Ich bin immer noch nicht überzeugt, dass dies optimal ist ... Ich werde in den nächsten Tagen nicht viel Zeit haben, ich werde irgendwann eine Erklärung hinzufügen.

Martin Ender
quelle
5

Pyth, 62 Bytes

JvXz"() ,][")u?qJQG&=J?K}Quu+GHNY<J1)hJtJ++XWK"(cdr "\d\aG\)\l

Probieren Sie es online aus: Demo oder Test Suite

Erläuterung:

Das erste Bit JvXz"() ,][")ersetzt die Zeichen "() "durch die Zeichen "[],"in der Eingabezeichenfolge, was zur Darstellung einer Liste im Python-Stil führt. Ich bewerte es und speichere es in J.

Dann reduziere ich den String G = "l"mit u...\l. Ich wende die innere Funktion ...wiederholt an G, bis sich der Wert von Gnicht mehr ändert, und drucke dann G.

Die innere Funktion führt Folgendes aus: Wenn Jbereits gleich der eingegebenen Nummer ist, ändern Sie nicht G( ?qJQG). Ansonsten mache ich die Liste flach J[:1]und überprüfe, ob sich die eingegebene Nummer in dieser Liste befindet und speichere diese in der Variablen K( K}Quu+GHNY<J1)). Beachten Sie, dass Pyth keinen Flatten-Operator hat. Dies nimmt also einige Bytes in Anspruch. Wenn Kja, dann aktualisiere ich J mit J[0], ansonsten mit J[1:]( =J?KhJtJ). Und dann ersetze ich Gmit "(cdr G)"und ersetze ddas a, wenn Kes wahr ist ( ++XWK"(cdr "\d\aG\)).

Jakube
quelle
5

Schema (R5RS), 102 Bytes

(let g((l(read))(n(read))(o'l))(if(pair? l)(or(g(car l)n`(car,o))(g(cdr l)n`(cdr,o)))(and(eq? n l)o)))
Anders Kaseorg
quelle
1

PHP - 177 Bytes

Ich habe einige Zeilen hinzugefügt, um die Lesbarkeit zu verbessern:

function f($a,$o,$n){foreach($a as$v){if($n===$v||$s=f($v,$o,$n))return
'(car '.($s?:$o).')';$o="(cdr $o)";}}function l($s,$n){echo f(eval(strtr
("return$s;",'() ','[],')),l,$n);}

Hier ist die ungolfed Version:

function extractPhp($list, $output, $number)
{
    foreach ($list as $value)
    {
        if (is_int($value))
        {
            if ($value === $number) {
                return '(car '. $output .')';
            }
        }
        else
        {
            $subOutput = extractPhp($value, $output, $number);
            if ($subOutput !== null) {
                return '(car '. $subOutput .')';
            }
        }

        $output = '(cdr '. $output .')';
    }
}

function extractLisp($stringList, $number)
{
    $phpCode = 'return '. strtr($stringList, '() ','[],') .';';
    $list = eval($phpCode);
    echo extractPhp($list, 'l', $number);
}
Schwarzes Loch
quelle
1

Haskell, 190 188 Bytes

l "(4 5 (1 2 (7) 9 (10 8 14)))" 8

bewertet zu

"(car (cdr (car (cdr (cdr (cdr (cdr (car (cdr (cdr l))))))))))"

l(h:s)n=c$i(show n)s""""
i n(h:s)t l|h>'/'&&h<':'=i n s(t++[h])l|t==n='a':l|h=='('=j$'a':l|h==')'=j$tail$dropWhile(=='d')l|0<1=j$'d':l where j=i n s""
c[]="l"
c(h:s)="(c"++h:"r "++c s++")"
Leif Willerts
quelle
1
Sie können (und cin Funktion cin eine Zeichenfolge verwandeln :c(h:s)="(c"++h:...
nimi
Wow, hätte nicht gedacht, dass das funktionieren würde, hwenn man ein Char wäre!
Leif Willerts
0

Common Lisp, 168.155 Bytes

Irgendeine blöde Rekursionssache, es könnte wahrscheinlich ein bisschen mehr komprimiert werden:

(lambda(l e)(labels((r(l o)(setf a(car l)d(cdr l)x`(car,o)y`(cdr,o))(if(equal e a)x(if(atom a)(r d y)(if(find e l)(r d y)(if d(r d y)(r a x)))))))(r l'l)))

Schön gedruckt:

(lambda (l e)
  (labels ((r (l o)
             (setf a (car l) d (cdr l)
                   x `(car ,o) y `(cdr ,o))
             (if (equal e a) x
                 (if (atom a)
                     (r d y)
                     (if (find e l)
                         (r d y)
                         (if d
                             (r d y)
                             (r a x)))))))
    (r l 'l)))
Kindermädchen
quelle