Forme di sosia


23

Figure simili

Due rettangoli sono simili se i rapporti dei loro lati sono gli stessi.

Considera questi due rettangoli; un rettangolo alto 5 righe e largo 11 caratteri:

===========
===========
===========
===========
===========

e un rettangolo alto 10 righe e largo 22 caratteri:

======================
======================
======================
======================
======================
======================
======================
======================
======================
======================

Queste forme sono simili perché i rapporti dei loro lati sono gli stessi. Per dirla formalmente (con h come lato più corto e w come lato più lungo):

h1w1=h2w2

Puoi anche fare:

h1h2=w1w2

La sfida

Scrivi un programma o una funzione che accetta un rettangolo "principale" e alcuni rettangoli "altri" e stampa quali degli "altri" sono simili a "principali".

L'input

Una forma e un elenco di forme. Ogni forma è composta da 2 numeri interi positivi diversi da zero, che indicano la larghezza e l'altezza del rettangolo. Ad esempio, questo:

(4,2), (3,9)

indica due rettangoli, un 4x2 e un 3x9. Il formato esatto dell'input può essere come desideri.

L'output

Gli indici delle "altre" forme simili a "principali". È possibile scegliere se gli indici sono basati su 0 o 1, nonché il formato e l'ordine esatti dell'output.

Programma di esempio

In Python:

main = eval(raw_input()) # The main rectangle.
rects = eval(raw_input()) # The list of rectangles.
similar = set()
for i, rect in enumerate(rects):
    if max(main)*min(rect) == min(main)*max(rect): # Cross-multiply
        # They are similar.
        similar.add(i)

print similar

Input e output di esempio

Ingresso:

(1, 2)
[(1, 2), (2, 4)]

Produzione:

set([0, 1])

Ingresso:

(1, 2)
[(1, 9), (2, 5), (16, 8)]

Produzione:

set([2])

vincente

Questo è code-golf, quindi vince l'invio più breve.

Gli appunti

  • Ciò dovrebbe essere ovvio, ma le scappatoie standard sono vietate .
  • Non è possibile utilizzare builtin per individuare figure simili. (Non so nemmeno se esiste, ma non sarei sorpreso!)

È consentito l'uso della divisione in virgola mobile? Sarebbe [1.0 2.0]un formato di input accettabile?
Dennis,

@Dennis A condizione che la lingua selezionata non abbia una precisione in virgola mobile stranamente bassa e quindi i casi di test falliscono, dovrebbe andare bene. ;)
kirbyfan64sos il

Invece di indici, possiamo anche produrre da soli le stesse forme simili?
orlp

@orlp Nope !!! : D
kirbyfan64sos

3
Il formato di output di emissione degli indici è obbligatorio? Per un caso di test come [(1,2), (2,4), (1,9), (2,5), (16,8)], è solo [0,1,4]e [1,2,5]consentito, oppure potremmo anche produrre [1,1,0,0,1]o [(1,2), (2,4), (16,8)]?
Kevin Cruijssen,

Risposte:



11

Python, 61 byte

lambda a,b,l:[i for i,(x,y)in enumerate(l)if x/y in[a/b,b/a]]

Sì, sto usando spendere 9 caratteri per scrivere enumerate. Accetta input come 1, 2, [(1, 9), (3,6), (2, 5), (16, 8)]. Per Python 2, i valori di input devono essere scritti come float.

Un carattere più lungo (62) in Python 3:

def f(a,b,l,i=0):
 for x,y in l:b/a!=x/y!=a/b or print(i);i+=1

Ti dispiace spiegarlo? Mi piacerebbe sapere cosa sta succedendo.
The_Basset_Hound

@BassetHound per ogni elemento nell'elenco di input, la comprensione decomprime icome indice e (x,y)come punto. Quindi controlla se il valore x/yè uguale al quoziente iniziale ( a/b) dei due numeri o al suo reciproco ( b/a). Se è uguale a uno di questi valori, quel valore iviene aggiunto all'elenco, altrimenti viene scartato.
FryAmTheEggman

9

CJam, 22 20 19 byte

{:$::/_0=f=ee::*0-}

Quanto sopra è una funzione anonima che estrae un singolo array di coppie in virgola mobile (la prima coppia è ago) dallo stack e invia in cambio l'array di indici basati su 1.

Provalo online nel CJam .

Come funziona

:$                e# Sort each pair.
  ::/             e# [a b] -> a/b
     _0=          e# Push a copy of the array and extract the first float (needle).
        f=        e# Check which floats are equal to the needle.
          ee      e# Enumerate the resulting Booleans.
            ::*   e# Multiply each Boolean by its index.
                  e# This yields 0 for the needle (index 0) and for non-matching
                  e# haystack pairs (Boolean 0).
               0- e# Remove all zeroes from the array.

8

Haskell , 48 byte

(a!b)l=[i|(i,(x,y))<-zip[0..]l,x/y+y/x==a/b+b/a]

Provalo online!

Chiamalo così (!) 1 2 [(1, 9), (3,6), (2, 5), (16, 8)].

Una porta vicina alla mia risposta Python . L'espressione zip[0..]lenumera l'elenco con i suoi indici.

L'espressione x/y+y/x==a/b+b/averifica che il rapporto x/ysia a/bo b/a, poiché la funzione f(z) = z + 1/zha f(z) = f(1/z)e non ci sono altre collisioni.


Forse fare in modo che hun operatore prenda tre argomenti? Ciò consentirebbe di risparmiare un byte e penso che rimarrebbe all'interno delle regole.
dfeuer

@dfeuer Certo, è sicuramente consentito dagli standard moderni anche se indietro era più sfocato ciò che le libertà potevano essere prese con l'I / O.
xnor

7

Snowman 1.0.2 , 61 caratteri

}vgvgaC"[0-9]+"sM:10sB;aM2aG:AsO:nD;aF;aM0AAgaA*|:#eQ;AsItSsP

Incredibile puro (a meno che tu non conosca Snowman), anche esattamente in linea con l'obiettivo di design del linguaggio di essere il più confuso possibile.

Il formato di input è lo stesso del post, anche il formato di output è lo stesso meno set(e) .

Ungolfed (o non minified, davvero):

}vgvgaC     // read two lines of input, concatenate
"[0-9]+"sM  // use a regex to grab all numbers
:10sB;aM    // essentially map(parseInt)
2aG         // take groups of 2 (i.e. all the ordered pairs)

// now map over each ordered pair...
:
  AsO       // sort
  :nD;aF    // fold with division - with 2 array elements, this is just a[0]/a[1]
;aM

// we now have an array of short side to long side ratios
// take out the first one
0AAgaA      // active vars beg, b=array[0], g=the rest
*|          // store first ordered pair in permavar, bring the rest to top

// select indices where...
:
  #         // retrieve first ordered pair
  eQ        // equal?
;AsI

tSsP  // to-string and output

Sono abbastanza orgoglioso di alcuni dei trucchi che ho usato in questo:

  • Ho usato lo stesso formato di input del post. Ma invece di cercare di analizzarlo in qualche modo, il che sarebbe davvero disordinato, ho semplicemente concatenato le due linee e quindi ho usato una regex per estrarre tutti i numeri in un unico array (con il quale poi ho fatto 2aG, cioè ottenere ogni gruppo di 2).

  • :nD;aFè piuttosto elegante. Prende semplicemente una matrice di due elementi e divide il primo per il secondo. Il che sembra piuttosto semplice, ma farlo in modo intuitivo ( a[0]/a[1]) sarebbe molto, molto più lungo in Snowman: 0aa`NiN`aA|,nD(e questo presuppone che non dobbiamo preoccuparci di fare confusione con altre variabili esistenti). Invece, ho usato il metodo "fold" con un predicato di "divide", che, per un array di due elementi, ottiene la stessa cosa.

  • 0AAgaAsembra abbastanza innocuo, ma ciò che effettivamente fa è archiviare un 0alle variabili, quindi prende tutte le variabili con un indice maggiore di quello (quindi, tutte le variabili tranne la prima). Ma il trucco è, invece di AaG(che eliminerebbe l'array originale e il 0), che ho usato AAg, che mantiene entrambi. Ora uso aAat-index, usando lo stesso0 per ottenere il primo elemento dell'array; inoltre, questo è in modalità consumo ( aAanziché aa), quindi elimina anche l' 0array originale, che ora è immondizia per noi.

    Ahimè, 0AAgaA*|lo fa essenzialmente la stessa cosa che GolfScript fa in un carattere: (. Tuttavia, penso ancora che sia piuttosto carino, secondo gli standard di Snowman. :)


3

Mathematica, 41 byte

Position[a=Sort@#;Sort@#/a&/@#2,{x_,x_}]&

Uso:

Position[a = Sort@#; Sort@#/a & /@ #2, {x_, x_}] &[{1, 2}, {{1, 2}, {2, 5}, {16, 8}}]
(* {{1}, {3}} *)

1
Sapevo solo che Mathematica sarebbe venuta fuori in qualche modo!
kirbyfan64sos,

3

Pyth - 14 byte

Filtra confrontando i quozienti, quindi le mappe indexOf.

xLQfqcFSTcFvzQ

Test Suite .


Questo non ordina la forma principale, quindi darà la risposta sbagliata quando la lunghezza del primo lato della forma principale è maggiore. Vedi questo test case
isaacg

@isaacg buon punto, risolverà.
Maltysen,

Questo fallisce su input con elementi ripetuti, per esempio 1,2e [(1, 2), (2, 4), (1, 2)]darà [0, 1, 0]piuttosto che il corretto [0, 1, 2].
orlp,

Voglio accettare questo, poiché è il più breve, ma il problema menzionato da @orlp è stato risolto?
Kirbyfan64sos,

1
@ kirbyfan64sos No.
orlp,

3

APL (Dyalog Unicode) , 16 13 byte SBCS

(=.×∘⌽∨=.×)⍤1

Provalo online!

-3 grazie a @ngn!

Spiegazione:

(=.×∘⌽∨=.×)⍤1
(        )    "OR" together...
 =.    =.      ...fold by equality of:
   ×∘⌽         - the arguments multiplied by itself reversed
         x     - the argument multiplied by itself
           1  Applied at rank 1 (traverses)

Il formato di output è un vettore binario come il 1 1 0 0 1quale un "altro" rettangolo è simile.

APL (Dyalog Extended) , SBCS da 11 byte

=/-×⍥(⌈/)¨⌽

Provalo online!

Spiegazione:

=/-×⍥(⌈/)¨⌽  takes only a right argument: ⍵, shape: (main (other...))
            two transformations:
  -          - left (L) vectorized negation: -⍵
            - right (R): reverse. (main other) => (other main)
     (⌈/)¨   transformation: calculate the max (since L is negated, it calculates the min)
             (/ reduces over  max)
             this vectorizes, so the "main" side (with only one rect) will get repeated once for each "other" rect on both sides
   ×⍥        over multiplication: apply the transformation to both sides. F(LF(R)
=/           reduce the 2-element matrix (the "main" that's now the side of the "other") to check which are equal

Il formato di output è lo stesso della risposta Dyalog principale.

Grazie ad Adám per l'aiuto golf + Extended.


(=.×∘⌽∨=.×)⍤1
ngn,

Grazie. Proverà a ispezionarlo per primo
Ven,

2

Julia, 62 byte

f(m,o)=find([(t=sort(m).*sort(i,rev=true);t[1]==t[2])for i=o])

Il find funzione individua gli elementi veri in un vettore booleano. .*esegue la moltiplicazione elementwise dei vettori.

Ungolfed:

function f(m::Array, o::Array)
    find([(t = sort(m) .* sort(i, rev=true); t[1] == t[2]) for i in o])
end

Uso:

f([1,2], {[1,9], [2,5], [16,8]})

2

K5, 19 byte

Penso che questo farà il trucco:

&(*t)=1_t:{%/x@>x}'

Prende un elenco di coppie in cui il primo è il "principale". Calcola il rapporto dividendo le dimensioni ordinate di ciascuna coppia. Restituisce un elenco delle posizioni indicizzate 0 delle coppie corrispondenti. (probabilmente il formato di input che ho scelto rende questo -1 indicizzato- se questo è considerato un tack non valido su a1+ di partenza all'inizio e aggiungi due caratteri alla dimensione del mio programma.)

Esempio di utilizzo:

  &(*t)=1_t:{%/x@>x}'(1 2;1 2;2 4;2 5;16 8)
0 1 3

Questo funziona in oK - nota che dipendo implicitamente dalla divisione producendo sempre risultati in virgola mobile. Funzionerebbe in Kona se aggiungessi un punto decimale a tutti i numeri nell'input e aggiungi uno spazio dopo il _.


2

Octave / Matlab, 44 byte

Utilizzando una funzione anonima:

@(x,y)find((max(x))*min(y')==min(x)*max(y'))

Il risultato è nell'indicizzazione basata su 1.

Per usarlo, definire la funzione

>> @(x,y)find((max(x))*min(y')==min(x)*max(y'));

e chiamalo con il seguente formato

>> ans([1 2], [1 9; 2 5; 16 8])
ans =
     3

Puoi provarlo online .


Se il risultato può essere in indicizzazione logica ( 0indica non simile, 1indica simile): 38 byte :

@(x,y)(max(x))*min(y')==min(x)*max(y')

Stesso esempio di cui sopra:

>> @(x,y)(max(x))*min(y')==min(x)*max(y')
ans = 
    @(x,y)(max(x))*min(y')==min(x)*max(y')

>> ans([1 2], [1 9; 2 5; 16 8])
ans =
 0     0     1

2

Brachylog , 14 byte

z{iXhpᵐ/ᵛ∧Xt}ᵘ

Provalo online!

Prende l'input come un elenco contenente un elenco contenente il rettangolo principale e l'elenco di altri rettangoli (quindi lo è il caso di test 1 [[[1,2]],[[1,2],[2,4]]]) e genera un elenco di indici basati su 0 attraverso la variabile di output.

z                 Zip the elements of the input, pairing every "other" rectangle with the main rectangle.
 {          }ᵘ    Find (and output) every unique possible output from the following:
  iX              X is an element of the zip paired with its index in the zip.
    h             That element
      ᵐ           with both of its elements
     p            permuted
        ᵛ         produces the same output for both elements
       /          when the first element of each is divided by the second.
         ∧Xt      Output the index.

Se quel tipo di formattazione di input strana e specifica sta tradendo, è un po 'più lungo ...

Brachylog , 18 byte

{hpX&tiYh;X/ᵛ∧Yt}ᶠ

Provalo online!

Prende l'input come un elenco contenente il rettangolo principale e l'elenco di altri rettangoli (quindi il caso di test 1 è il più ovvio [[1,2],[[1,2],[2,4]]]) e genera un elenco di indici basati su 0 attraverso la variabile di output.

{               }ᵘ    Find (and output) every possible output from the following:
  p                   A permutation of
 h                    the first element of the input
   X                  is X,
    &                 and
      i               a pair [element, index] from
     t                the last element of the input
       Y              is Y,
        h             the first element of which
            ᵛ         produces the same output from
           /          division
         ;            as
          X           X.
             ∧Yt      Output the index.

Per determinare se due coppie larghezza-altezza rappresentano rettangoli simili, sono sufficienti i quattro byte pᵐ/ᵛ(che generano il rapporto condiviso o il suo reciproco). Tutto il resto sta gestendo i rettangoli multipli da confrontare e l'output è costituito da indici.


2

dzaima / APL , 7 byte

=/⍤÷⍥>¨

Provalo online!

8 byte che producono un elenco di indici anziché un vettore booleano

      ¨ for each (pairing the left input with each of the right)
    ⍥>    do the below over sorting the arguments
=/          equals reduce
           after
   ÷        vectorized division of the two

Sebbene sia una buona risposta, dobbiamo produrre gli indici. Quindi il tuo caso di test TIO dovrebbe risultare in uno [0,1,4]o [1,2,5](non sono sicuro se la tua lingua è indicizzata 0 o 1). Sarebbe stata una sfida migliore se fossero consentiti tutti e tre i formati di output: indici; filtro per mantenere i valori di verità; elenco di valori di verità / falsità (come hai fatto ora), anziché solo indici consentiti.
Kevin Cruijssen,

@KevinCruijssen "Puoi scegliere il [...] formato e l'ordine esatti dell'output." in APL è pratica molto comune archiviare gli indici come vettore booleano, ma hai ragione, probabilmente dovrebbe essere chiarito.
dzaima,

Beh, ho letto " Si può scegliere se gli indici sono 0- o 1-based, così come il formato esatto e l'ordine della produzione. " Come può essere [0,1,4], [1,2,5], 4\n0\n1, 5 2 1, ecc ecc, dal momento che ancora dichiarato indici . Ma ho chiesto a OP di chiarire (se rispondono, dato che si tratta di una sfida di 4 anni). Nella mia risposta 05AB1E significherebbe 14 byte se gli indici sono obbligatori contro 8 byte se una delle altre due opzioni è consentita. Indipendentemente da ciò, ho votato a favore della tua risposta. :)
Kevin Cruijssen il



1

PowerShell , 58 56 byte

-2 byte grazie a mazzy x2

param($x,$y,$b)$b|%{($i++)[$x/$y-($z=$_|sort)[0]/$z[1]]}

Provalo online!

Ciò abusa leggermente della input may be however you desireclausola facendo in modo che i componenti della prima forma vengano separati per salvare 3 byte.

PowerShell , 61 59 byte

param($a,$b)$b|%{($i++)[$a[0]/$a[1]-($x=$_|sort)[0]/$x[1]]}

Provalo online!

Utilizza l'indicizzazione condizionale per scambiare l'indice in base zero corrente e null in base all'allineamento o meno dei rapporti. Fortunatamente in questo caso, $iaumenta indipendentemente dal fatto che sia stampato o meno.


1
È possibile risparmiare di più se si utilizza -invece -ne.
mazzy

0

Javascript (ES6), 75

(a,b)=>b.filter(e=>e.l*a.h==a.l*e.h||e.l*a.l==a.h*e.h).map(e=>b.indexOf(e))

Alternativa, anche 75

(a,b)=>b.map((e,i)=>e.l*a.h==a.l*e.h||e.l*a.l==a.h*e.h?i:-1).filter(e=>e+1)

L'input viene considerato come un oggetto JSON e una matrice di oggetti JSON

{
    l: length of rectangle,
    h: height of rectangle
}

Non penso che questo funzioni con il secondo caso di test.
kirbyfan64sos,

@ kirbyfan64sos scusa non ho visto quella parte. È stato risolto (ma sono sicuro di poterlo giocare di più)
DankMemes,

Questi non sono oggetti JSON, questi sono semplici oggetti javascript. JSON è un formato di trasferimento dati.
edc65,

0

05AB1E , 15 14 byte

ʒ‚ε{ü/}Ë}J¹Jsk

Provalo online o verifica tutti i casi di test .

Spiegazione:

ʒ               # Filter the (implicit) input-list by:
               #  Pair the current width/height with the (implicit) input width/height
  ε             #  Map both width/height pairs to:
   {            #   Sort from lowest to highest
    ü/          #   Pair-wise divide them from each other
              #  After the map: check if both values in the mapped list are equals
        }J      # After the filter: join all remaining pairs together to a string
          ¹J    # Also join all pairs of the first input together to a string
            s   # Swap to get the filtered result again
             k  # And get it's indices in the complete input-list
                # (which is output implicitly)

Il J oin ci sono perché 05AB1E non può determinare gli indici su liste multidimensionali dopo


Se l'output delle coppie larghezza / altezza che sono veritiere o l'output di un elenco di valori di verità / falsità basato sull'elenco di input, potrebbero invece essere 8 byte :

ʒ‚ε{ü/}Ë

Provalo online o verifica tutti i casi di test .

ε‚ε{ü/}Ë

Provalo online o verifica tutti i casi di test .

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.