Gira la calcolatrice


16

Introduzione:

Diamo un'occhiata a una calcolatrice standard in Windows: per questa sfida, esamineremo solo i seguenti pulsanti e ignoreremo tutto il resto:
inserisci qui la descrizione dell'immagine

7 8 9 /
4 5 6 *
1 2 3 -
0 0 . +

Sfida:

Input:
riceverai due input:

  • Uno è qualcosa per indicare la rotazione con incrementi di 90 gradi
  • L'altro è un elenco di coordinate che rappresentano i pulsanti premuti sul calcolatore ruotato.

Sulla base del primo input, ruotiamo il layout sopra menzionato in senso orario con incrementi di 90 gradi. Quindi, se l'input è 0 degrees, rimane com'è; ma se l'ingresso è 270 degrees, verrà ruotato tre volte in senso orario (o una volta in senso antiorario). Ecco i quattro possibili layout:

Default / 0 degrees:
7 8 9 /
4 5 6 *
1 2 3 -
0 0 . +

90 degrees clockwise:
0 1 4 7
0 2 5 8
. 3 6 9
+ - * /

180 degrees:
+ . 0 0
- 3 2 1
* 6 5 4
/ 9 8 7

270 degrees clockwise / 90 degrees counterclockwise:
/ * - +
9 6 3 .
8 5 2 0
7 4 1 0

Il secondo input è un elenco di coordinate in qualsiasi formato ragionevole . Ad esempio (array di numeri interi 2D con indice 0):

[[1,2],[2,3],[0,3],[1,0],[1,1]]

Output:
produciamo sia la somma, sia il risultato (e un segno di uguale =).

Esempio:
quindi se l'input è 270 degreese [[1,2],[2,3],[0,3],[1,0],[1,1]], l'output diventerà:

517*6=3102

Regole della sfida:

  • Gli ingressi possono essere in qualsiasi formato ragionevole. Il primo ingresso può essere 0-3, 1-4, A-D, 0,90,180,270, ecc Il secondo ingresso può essere una matrice 2D 0-indicizzato, matrice 1 indicizzati 2D, una stringa, Lista di punti-oggetti, ecc La chiamata. È anche possibile scambiare le coordinate xey rispetto agli input di esempio forniti. Indica quali formati di input hai utilizzato nella tua risposta!
  • Puoi aggiungere spazi (ad es. 517 * 6 = 3102) Se lo desideri.
  • Puoi aggiungere zeri finali dopo la virgola, a un massimo di tre (ovvero 3102.0/ 3102.00/ 3102.000anziché 3102o 0.430anziché 0.43).
  • Non è consentito aggiungere parentesi all'output, quindi (((0.6+4)-0)/2)/4=0.575non è un output valido.
  • Puoi usare altri simboli di operando per la tua lingua. Così ×o ·invece di *; o ÷invece di /; eccetera.
  • Poiché una calcolatrice calcola automaticamente quando si introduce un operando, è necessario ignorare la precedenza dell'operatore! Quindi si 10+5*3otterrà 45( (10+5)*3=45), non 25( 10+(5*3)=25)
    (cioè 10+5*(ora visualizza 15 sul display) → 3=(ora visualizza la risposta 45)). Tienilo a mente quando usi evale funzioni simili sulla somma risultante.
  • Non ci saranno casi di test per la divisione per 0.
  • Non ci saranno casi di test con più di tre cifre decimali di conseguenza, quindi non è necessario arrotondare il risultato.
  • Non ci saranno casi di test in cui più operandi si susseguono o in cui due punti si susseguono.
  • Non ci saranno casi di test per numeri negativi. Il segno meno ( -) verrà utilizzato solo come operando, non come negativo.
  • Non ci saranno casi di test .##senza un numero iniziale prima della virgola (cioè 2+.7non sarà un caso di test valido, ma 2+0.7potrebbe esserlo).

Regole generali:

  • Questo è , quindi vince la risposta più breve in byte.
    Non lasciare che le lingue di code-golf ti scoraggino dal pubblicare risposte con lingue non codegolfing. Prova a trovare una risposta il più breve possibile per "qualsiasi" linguaggio di programmazione.
  • Per la tua risposta valgono regole standard , quindi puoi usare STDIN / STDOUT, funzioni / metodo con i parametri corretti, programmi completi. La tua chiamata.
  • Sono vietate le scappatoie predefinite .
  • Se possibile, aggiungi un link con un test per il tuo codice.
  • Inoltre, si prega di aggiungere una spiegazione, se necessario.

Casi test:

Input:   270 degrees & [[1,2],[2,3],[0,3],[1,0],[1,1]]
Output:  517*6=3102

Input:   90 degrees & [[3,1],[0,0],[0,1],[3,3],[2,0],[0,3],[0,0],[0,2],[3,0],[2,1]]
Output:  800/4+0.75=200.75

Input:   0 degrees & [[0,0],[1,0],[2,0],[3,0],[1,2],[2,1],[2,2]]
Output:  789/263=3

Input:   180 degrees & [[3,0],[1,0],[1,2],[0,0],[3,2],[0,1],[2,0],[0,3],[2,1],[0,3],[3,2]]
Output:  0.6+4-0/2/4=0.575

1
I casi di test hanno molti errori (ad esempio, il 3 ° e il 4 ° hanno X e Y scambiati (il 1 ° non lo fa) e non so nemmeno cosa sia successo al 2 °)
dzaima,

2
Il programma dovrebbe gestire strane pressioni di pulsanti? 1+-*/+-*/2darà 0.5su Windows (10) calcolatrice.
user202729

1
il secondo caso di test dovrebbe iniziare con[1,3],
Uriel,

1
Dobbiamo gestire i decimali meno di 1 senza 0 iniziali, come in 2+.7?
Tutleman,

4
La precedenza dell'operatore è il motivo per cui non uso mai Windows Calculator in modalità standard.
Neil,

Risposte:



3

Dyalog APL, 94 88 86 85 byte

{o,'=',⍎('('\⍨+/'+-×÷'∊⍨o),'[×÷+-]'⎕R')&'⊢o←(((⌽∘⍉⍣⍺)4 4⍴'789÷456×123-00.+')⊃⍨⊂∘⊢)¨⍵}

Provalo online!

Prende le rotazioni come argomento a sinistra 0-3e gli indici basati su 1 come argomento a destra, come un elenco di y xcoordinate, come (1 1)(2 3)(4 5)ecc.

Ciò è diventato piuttosto disordinato a causa della valutazione destrorsa delle espressioni in APL.


3

C (gcc) , 282294 295 296 300 304 306 310 byte

Tutte le ottimizzazioni devono essere disattivate e funzionano solo su GCC a 32 bit.

float r,s;k,p,l,i;g(d,x,y){int w[]={y,x,3-y,3-x,y};d=w[d+1]*4+w[d];}f(x,y,z)int**z;{for(i=0;i<=y;i++)putchar(k=i-y?"789/456*123-00.+"[g(x,z[i][0],z[i][1])]:61),57/k*k/48?p?r+=(k-48)*pow(10,p--):(r=10*r+k-48):k-46?s=l?l%2?l%5?l&4?s/r:s+r:s-r:s*r:r,r=p=0,l=k:(p=-1);printf("%.3f",s);}

1 byte grazie a @Orion!

Provalo online!

Prototipo di funzione:

f(<Direction 0-3>, <Number of entries>, <a int** typed array in [N][2]>)

Formato di input (come su TIO):

<Direction 0~3> <Number of entries>
<Entries 0 Row> <Entries 0 Column>
<Entries 1 Row> <Entries 1 Column>
....
<Entries N Row> <Entries N Column>

Versione non golfata con commenti:

float r, s;
k, p, l, i;
g(d, x, y) {
  int w[] = {
    y,
    x,
    3 - y,
    3 - x,
    y
  };
  d = w[d + 1] * 4 + w[d];
}
f(x, y, z) int **z; {
  for (i = 0; i <= y; i++)
  {
      putchar(k = i - y ? 
      "789/456*123-00.+"[g(x, z[i][0], z[i][1])] : 61),     // Print character, otherwise, '='
      57 / k * k / 48 ?                                     // If the character is from '0'~'9'
        p ?                                                 // If it is after or before a dot
            r += (k - 48) * pow(10., p--)                   // +k*10^-p
        :
            (r = 10 * r + k - 48)                           // *10+k
      :
          k - 46 ?                                          // If the character is not '.', that is, an operator, + - * / =
            s = l ?                                         // Calculate the result of previous step (if exist)
                    l % 2 ?                                 // If + - /
                        l % 5 ?                             // If + /
                            l & 4 ?
                                s / r
                            :
                                s + r
                        :
                            s - r
                    :
                        s * r
                 :
                    r,
                    r = p = 0, l = k                        // Reset all bits
          :
            (p = -1);                                       // Reverse the dot bit
  }
  printf("%.3f", s);
}

Il codice può gestire casi come 1+.7o -8*4.

Molto triste C non ha un eval😭.


Puoi davvero ritenere casi come 3*-5non validi. L'ho specificato nelle regole.
Kevin Cruijssen,

Considerando che la precisione richiesta nelle regole è di soli 3 posti, è possibile sostituirla doublecon floatun byte libero. Inoltre, non è putc()identico a putchar()? Potrei sbagliarmi però.
Orione,

@Orion Ricordo che è putcnecessario un secondo argomento per specificare su quale stream stai scrivendo?
Keyu Gan,


2

JavaScript (ES6), 162 160 157 byte

Accetta input come orientamento oe matrice di coordinate (y, x)a nella sintassi del curry (o)(a).

L'orientamento è un numero intero in [0..3] :

  • 0 = 0 °
  • 1 = 90 ° in senso orario
  • 2 = 180 ° in senso orario
  • 3 = 270 ° in senso orario
o=>a=>(s=a.map(([y,x])=>'789/456*123-00.+'[[p=y*4+x,12+(y-=x*4),15-p,3-y][o]]).join``)+'='+eval([...x=`0)+${s}`.split(/(.[\d.]+)/)].fill`(`.join``+x.join`)`)

Casi test


2

Rubino , 135 133 132 byte

->r,c{a="";c.map{|x,y|a=((w="789/456*123-00.+"[[y*4+x,12-x*4+y,15-y*4-x,x*4+3-y][r]])=~/[0-9.]/?a:"#{eval a}")+w;w}*""+"=#{eval a}"}

Provalo online!

Orientamento come numero intero: 0 per 0 °, 1 per 90 ° e così via.


1

Python 3, 235 234 230 byte

Un po 'brutto ma funziona per tutti i casi di test tranne il primo, che non sembra corrispondere al calcolatore di esempio. Prendo la rotazione come 0-3 (0-270) e moltiplico per 16 per compensare.

eval() è un built-in che tenta di compilare stringhe come codice e gestisce la conversione dei simboli di testo in operatori.

import re
def f(r,c,J=''.join):
 b='789/456*123-00.+01470258.369+-*/+.00-321*654/987/*-+963.85207410'
 s=t=J([b[r*16+x*4+y]for y,x in c]);t=re.split('([\+\-\/\*])',s)
 while len(t)>2:t=[str(eval(J(t[0:3])))]+t[3:]
 print(s+'='+t[0])

Metodo alternativo, si è rivelato un po 'più a lungo ma mi piace molto questo suggerimento SO per ruotare l'array.

import re
def f(r,c):
 L=list;b=L(map(L,['789/','456*','123-','00.+']))
 while r:b=L(zip(*b[::-1]));r-=1
 s=''.join([b[x][y]for y,x in c]);t=re.split('([\+\-\/\*])',s)
 while len(t)>2:t=[str(eval(''.join(t[0:3])))]+t[3:]
 print(s+'='+t[0])

1

Java 10, 418 380 byte

d->a->{String r="",g=d>2?"/*-+963.85207410":d>1?"+.00-321*654/987":d>0?"01470258.369+-*/":"789/456*123-00.+",n[],o[];for(var i:a)r+=g.charAt(i[1]*4+i[0]);n=r.split("[-/\\+\\*]");o=r.split("[[0-9]\\.]");float s=new Float(n[0]),t;for(int i=1,O,j=0;++j<o.length;O=o[j].isEmpty()?99:o[j].charAt(0),s=O<43?s*t:O<44?s+t:O<46?s-t:O<48?s/t:s,i+=O>98?0:1)t=new Float(n[i]);return r+"="+s;}

Ho deciso di rispondere anche alla mia domanda. Sono sicuro che può essere giocato un po 'di più usando un approccio diverso.
Inserisci come int( 0-3) e int[][](0-indicizzato / lo stesso della descrizione della sfida). Output come floatcon iniziale .0se il risultato è un numero intero anziché un numero decimale.

Spiegazione:

Provalo qui.

d->a->{                       // Method with int & 2D int-array parameters and String return
  String r="",                //  Result-String, starting empty
    g=d>2?                    //  If the input is 3:
       "/*-+963.85207410"     //   Use 270 degree rotated String
      :d>1?                   //  Else if it's 2:
       "+.00-321*654/987"     //   Use 180 degree rotated String
      :d>0?                   //  Else if it's 1:
       "01470258.369+-*/"     //   Use 90 degree rotated String
      :                       //  Else (it's 0):
       "789/456*123-00.+",    //   Use default String
    n[],o[];                  //  Two temp String-arrays
  for(var i:a)                //  Loop over the coordinates:
    r+=g.charAt(i[1]*4+i[0]); //   Append the result-String with the next char
  n=r.split("[-/\\+\\*]");    //  String-array of all numbers
  o=r.split("[[0-9]\\.]");    //  String-array of all operands (including empty values unfortunately)
  float s=new Float(n[0]),    //  Start the sum at the first number
        t;                    //  A temp decimal
  for(int i=0,                //  Index-integer `i`, starting at 0
      O,                      //  A temp integer
      j=0;++j<o.length        //  Loop `j` over the operands
      ;                       //    After every iteration:
       O=o[j].isEmpty()?      //     If the current operand is an empty String
          99                  //      Set `O` to 99
         :                    //     Else:
          o[j].charAt(0),     //      Set it to the current operand character
       s=O<43?                //     If the operand is '*':
          s*t                 //      Multiply the sum with the next number
         :O<44?               //     Else-if the operand is '+':
          s+t                 //      Add the next number to the sum
         :O<46?               //     Else-if the operand is '-':
          s-t                 //      Subtract the next number from the sum 
         :O<48?               //     Else-if the operand is '/':
          s/t                 //      Divide the sum by the next number
         :                    //     Else (the operand is empty):
          s,                  //      Leave the sum the same
       i+=O>98?0:1)           //     Increase `i` if we've encountered a non-empty operand
    t=new Float(n[i]);        //   Set `t`  to the next number in line
  return r+"="+s;}            //  Return the sum + sum-result
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.