Trova l'ago nel pagliaio


38

Dato un pagliaio rettangolare di dimensioni almeno 2x2 composto da tutti gli stessi caratteri ASCII stampabili, emette la posizione (contando dalla parte superiore sinistra) dell'ago che è un carattere diverso.

Ad esempio, se viene inserito il seguente pagliaio:

#####
###N#
#####
#####

L'output dovrebbe essere 3,1 quando indicizzato zero (cosa userò in questa sfida) o 4,2quando indicizzato.

Il pagliaio può essere composto da qualsiasi carattere ASCII stampabile:

^^^
^^^
^N^
^^^
^^^
^^^

produzione: 1,2

e l'ago sarà qualsiasi altro carattere ASCII stampabile:

jjjjjj
j@jjjj
jjjjjj

produzione 1,1

È anche possibile avere un ago nell'angolo:

Z8
88

produzione 0,0

88
8Z

produzione 1,1

o per avere l'ago sul bordo:

>>>>>>>>>>
>>>>>>>>>:
>>>>>>>>>>

produzione 9,1

Regole e chiarimenti

  • Input e output possono essere dati da qualsiasi metodo conveniente . Questo significa che puoi prendere l'input come un elenco di un elenco di caratteri, come una singola stringa, ecc.
  • È possibile stampare il risultato su STDOUT o restituirlo come risultato di una funzione. Si prega di indicare nella richiesta in quale ordine si trova l'output (cioè orizzontale e verticale, come utilizzato nella sfida, o viceversa).
  • È accettabile un programma completo o una funzione.
  • Tu no scegliere quali personaggi usare. Questa è la sfida.
  • Il pagliaio è garantito per essere almeno 2x2, quindi non è ambiguo quale sia l'ago e quale sia il fieno.
  • C'è sempre un solo ago nell'input ed è sempre un solo carattere in termini di dimensioni.
  • Sono vietate le scappatoie standard .
  • Si tratta di quindi si applicano tutte le normali regole del golf e vince il codice più breve (in byte).

Caso di prova suggerito: 88\n8Z(con due caratteri ovviamente).
Kevin Cruijssen,

Possiamo prendere input come un array multidimensionale? cioè [['#', '#', '#', '#', '#'], ['#', '#', '#', 'N', '#'], ['#' , '#', '#', '#', '#'], ['#', '#', '#', '#', '#']];
640 KB

2
@gwaugh Ti piace un elenco di personaggi? Sì, va bene (ed esplicitamente chiamato OK).
AdmBorkBork,

3
Possiamo prendere input come una coppia di una stringa senza newline e la larghezza (o altezza) del pagliaio? vale a dire("########N###########", 5)
mio pronome è monicareinstate il

3
@someone Sì, anche se non ha un vero quorum , penso che dovrebbe essere permesso.
AdmBorkBork,

Risposte:


17

R , 49 47 44 byte

function(m,`?`=which)m==names(?table(m)<2)?T

Provalo online!

Prende input come una matrice, restituisce coordinate 1 indicizzate


4
Tale whichincarico è vergognosamente fluido.
CriminallyVulgar

4
Ero così entusiasta di provare questa sfida in R, poi l'ho visto e ho deciso invece di piangere in soggezione
Sumner18

9

Perl 6 ,41 38 37 byte

3 byte salvati grazie a @nwellnhof.

1 byte salvato grazie a Jo King.

{map {[+] ^∞Z*!<<.&[Z~~]},$_,.&[Z]}

Provalo online!

Spiegazione

Prende l'input come un elenco di elenchi di caratteri e restituisce un elenco di lunghezza 2 contenente coordinate X e Y a base zero dell'ago.

Funziona applicando il blocco {[+] ^∞ Z* !<<.&[Z~~]}sull'ingresso e sulla sua trasposizione. .&[Z~~]passa attraverso tutte le colonne dell'argomento e restituisce Truese tutti gli elementi sono uguali, Falsealtrimenti. Quindi neghiamo tutti i valori (quindi abbiamo un elenco con un bool per colonna, in cui il bool risponde alla domanda "L'ago è in quella colonna?"), Li moltiplichiamo dal punto di vista degli elementi con una sequenza 0,1,2 ,. .. ( True = 1e False = 0) e sommare l'elenco, quindi il risultato dell'intero blocco è il numero in base 0 della colonna in cui è stato trovato l'ago.

L'approccio migliore di Nwellnhof, Perl 6 , 34 byte

{map *.first(:k,*.Set>1),.&[Z],$_}

Provalo online!

Spiegazione

Generalmente lo stesso approccio, solo più efficace. Si usa ancora un blocco della matrice e la sua trasposizione, ma ora il blocco converte tutte le righe in Setse controlli per il numero di elementi. La firstfunzione fornisce quindi l'indice (dovuto al :k) della prima riga che conteneva più di 1 elemento. Per questo motivo, l'ordine $_e il .&[Z]bisogno di essere scambiati.


Bel approccio! 34 byte con first(:k), Sete .&[Z].
nwellnhof,

@nwellnhof, molto ben fatto. Fondamentalmente hai trovato quello che volevo trovare ma non sei riuscito a farlo: -. (Inoltre non avevo idea che tu potessi scrivere .&[Z].)
Ramillies,

In generale, .&[op]non sembra essere equivalente [op] $_ma funziona con Zqualche motivo.
nwellnhof,

@JoKing, grazie!
Ramillies,

9

Python 2 , 57 byte

lambda m:[map(len,map(set,a)).index(2)for a in zip(*m),m]

Provalo online!


Una porta di questo a Python 3 può essere di 62 byte :

lambda m:[[len(set(v))for v in a].index(2)for a in(zip(*m),m)]

La comprensione dell'elenco [len(set(v))for v in a], ora è più breve della doppia mappa di due byte poiché dovrebbe essere lanciata in un elenco comelist(map(len,map(set,a)))

Provalo online!


6

Brachylog , 20 byte

c≡ᵍ∋Ȯ&;I∋₎;J∋₎gȮ∧I;J

Provalo online!

Output [I,J], dove si Itrovano l'indice di riga e Jl'indice di colonna, entrambi con indice 0.

Stupidamente lungo, ma ottenere indici in Brachylog è di solito molto dettagliato.

Spiegazione

c                       Concatenate the Input into a single string
 ≡ᵍ                     Group identical characters together
   ∋Ȯ                   Ȯ is a list of One element, which is the needle character
     &;I∋₎              Take the Ith row of the Input
          ;J∋₎          Take the Jth character of the Ith row
              gȮ        That character, when wrapped in a list, is Ȯ
                ∧I;J    The output is the list [I,J]

6

PHP ,99 85 byte

Utilizzo di stringa senza newline e larghezza (o altezza) ('########N###########', 5) come input.

  • -5 byte rimuovendo chr () call, props a @Titus
  • -9 byte prendendo input come args a due funzioni, propaga anche a @Titus
function($a,$l){return[($p=strpos($a,array_flip(count_chars($a,1))[1]))%$l,$p/$l|0];}

Provalo online!

Ungolfed:

function need_hay( $a, $l ) {

    // identify the "needle" by counting the chars and 
    // looking for the char with exactly 1 occurrence
    // note: this is 1 byte shorter than using array_search()
    $n = array_flip( count_chars( $a, 1 ) )[1];

    // find the location in the input string
    $p = strpos( $a, $n );

    // row is location divided by row length, rounded down
    $r = floor( $p / $l );

    // column is remainder of location divided by row length
    $c = $p % $l;

    return array( $c, $r );

}

Produzione:

#####
###N#
#####
#####
[3,1]

^^^
^^^
^N^
^^^
^^^
^^^
[1,2]

jjjjjj
j@jjjj
jjjjjj
[1,1]

1
1) non è necessario chr: se il secondo parametro per strpos è un numero intero, verrà interpretato come un codice ASCII. -> -5 byte. 2) Due parametri di funzione $s,$wpossono salvare altri 9 byte.
Tito

@Titus, rimuovere chr () è geniale. Grazie! I parametri di funzionamento sono venuti in mente anche a me, semplicemente non volevo correre davanti a input req. Chiarirò con OP.
640 KB

5

05AB1E , 9 6 byte

Salvati 3 byte cambiando formato di input.

L'input è preso come una stringa e una lunghezza di riga.
L'output è un elenco a base zero del modulo[y, x]

D.mks‰

Provalo online! o come una suite di test

Spiegazione

D           # duplicate the input string
 .m         # get the least frequent character
   k        # get its index in the string
    s       # swap the row length to the top of the stack
     ‰      # divmod the index of the least frequent char with the row length

Dang, mi hai battuto. Stava lavorando su una risposta. Aveva appena finito un 13-byter. Ma il tuo è molto meglio, quindi +1. :) Dimenticato completamente .m..
Kevin Cruijssen,

@KevinCruijssen: Sì. Non credo di aver mai usato .mprima, ma ero abbastanza sicuro di averlo visto ad un certo punto :)
Emigna

5

Python 3 + NumPy , 75 66 byte

-9 byte grazie solo a @ ASCII

lambda x:where(x.view('i')-median(x.view('i')))
from numpy import*

Provalo online!

Ciò presuppone che l'input sia un array NumPy. L'output è indicizzato zero, prima verticale, poi orizzontale.

Converte l'input da chara intquindi calcola la mediana dell'array, che sarà il carattere pagliaio. Lo sottraggiamo dall'array, il che rende l'ago l'unico elemento diverso da zero. Infine, restituisci l'indice di quell'elemento con numpy.where().


1
Dato che sai che l'ingresso sarà ASCII (ovvero si inserisce in un byte) perché non utilizzarlo uint8per un byte in meno?
Draconis,

1
La lingua deve essere "Python 3 + numpy" qui poiché numpy non è incluso con la normale distribuzione di Python
ASCII, solo il

@Draconis che era in realtà il mio piano, ma che introduceva zeri tra i uint8codici ASCII corretti . Presumo che ciò sia dovuto al fatto che Python3 utilizza Unicode come formato di input standard per le stringhe.
hbaderts,


1
Va bene, dopotutto non è solo basato sulla tua soluzione, ma in genere non uso comunque il numpy. Inoltre, è inevitabile che una soluzione sia comunque molto simile dato che tutte le soluzioni sono pubbliche e questa è una sfida relativamente semplice
ASCII, solo il

4

Gelatina , 5 byte

Uscite [altezza, larghezza] (1 indicizzato).

ŒĠLÐṂ

Provalo online!

ŒĠLÐṂ – Monadic link / Full program. Takes a list of strings M as input.
ŒĠ    – Group the multidimensional indices by their values (treating M as a matrix).
  LÐṂ – And retrieve the shortest group of indices (those of the unique character).

Gelatina , 5 byte

ŒĠḊÐḟ

Provalo online!


4

Gelatina , 4 byte

Forse questo potrebbe essere stato solo un commento per Mr. Xcoder, è abbastanza simile ...

ŒĠEƇ

Un collegamento monadico che accetta la matrice di caratteri che produce un elenco di un elemento, la coordinata con 1 indice (riga, colonna) dall'alto in alto a sinistra.
(... Come programma completo, dato un argomento formattato in modo tale che l'analisi comporti un elenco di elenchi di caratteri - ovvero un elenco di stringhe in formato Python - viene stampata la singola coordinata.)

Provalo online!

Come?

ŒĠEƇ - Link: matrix, M
ŒĠ   - multi-dimensional indices grouped by Value
     -  ...due to the 2*2 minimum size and one needle this will be a list of two lists one
     -     of which will have length one (the needle coordinates as a pair) and the other
     -     containing all other coordinates as pairs
   Ƈ - filter keeping those for which this is truthy:
  E  -   all equal?
     -   ... 1 for the list of length 1, 0 for the list of at least 3 non-equal coordinates

1
Bene ... questo sembra limite, dal momento che è intelligente.
Erik the Outgolfer

4

JavaScript (ES6), 55 byte

Accetta input come (S)(w), where s is a string and w is the width of the matrix. Returns [x,y].

s=>w=>[(i=s.indexOf(/(.)\1+(.)/.exec(s+s)[2]))%w,i/w|0]

Try it online!


JavaScript (ES6),  65  64 bytes

Saved 1 byte thanks to @Neil

Takes input as a matrix of characters. Returns [x,y].

m=>m.some((r,y)=>r.some((c,x)=>!m[p=[x,y],~y&1].includes(c)))&&p

Try it online!

How?

We look for the first character c located at (x,y) which does not appear anywhere in another row r[Y]. We can perform this test on any row, as long as Yy. Because the input matrix is guaranteed to be at least 2×2, we can simply use Y=0 if y is odd or Y=1 if y is even.


1
~y&1 saves a byte over y&1^1.
Neil

4

Java 8, 132 111 bytes

m->{int c=m[0][0],i=0,j;for(c=m[1][0]!=c?m[1][1]:c;;i++)for(j=m[i].length;j-->0;)if(m[i][j]!=c)return i+","+j;}

-8 bytes (and -13 more implicitly) thanks to @dana.

Input as character-matrix.

Try it online.

Explanation:

m->{                    // Method with char-matrix parameter and String return-type
  int c=m[0][0],        //  Character to check, starting at the one at position 0,0
      i=0,j;            //  Index integers
  for(c=m[1][0]!=c?     //  If the second character does not equal the first:
         m[1][1]        //   Use the character at position 1,1 instead
        :c;             //  Else: keep the character the same
      ;i++)             //  Loop `i` from 0 indefinitely upwards:
    for(j=m[i].length;j-->0;)
                        //   Inner loop `j` in the range (amount_of_columns, 0]:
      if(m[i][j]!=c)    //    If the `i,j`'th character doesn't equal our character to check:
        return i+","+j;}//     Return `i,j` as result

1
124 - the final return statement should never get hit. There might be a better way to keep the outer loop going?
dana

@dana Thanks! As for: "There might be a better way to keep the outer loop going?", there certainly is; just removing it so it becomes an infinite loop. And then the return""; is unreachable and can be removed as well. :D So -21 bytes thanks to you.
Kevin Cruijssen

Interesting... I had tried removing the outer loop condition and was getting an unreachable code error. Didn't know that removing the final return was the fix.
dana

What exactly does the --> operator do in the inner loop? I was trying to find the java docs for that syntax but couldnt find anything
KBusc

1
@KBusc It's two operators: i-- and >. :) See this SO answer for more info. So the i > 0 is executed first, checking if i is larger than 0. And then i is decreased by 1 with i--, before it enters the body of the loop.
Kevin Cruijssen

3

MATL, 12 8 bytes

tX:XM-&f

Try it online!

Using the mode function as the majority-detector. Returns 1-based indices.

 t           % duplicate the input
  X:         % turn the copy into a linear array
    XM       % find the arithmetic mode of that (the 'haystack' character)
      -      % Subtract that from the original input
       &f    % find the position of the non-zero value in that result

-4 characters thanks to @LuisMendo


1
@LuisMendo Thanks. I don't think I knew about the 2 output version of find, even in MATLAB. (Hi, btw!)
sundar - Reinstate Monica

3

Wolfram Language 37 58 bytes

My earlier entry did not correctly handle the case where the "odd character out" was at the upper left corner of the matrix. This does.

#~Position~Keys[TakeSmallest[Counts@Flatten@#,1]][[1]]&

Counts@Flatten@# lists how many of each character are in the array, #.

TakeSmallest[...,1] returns the least frequent count, in the form of an association rule such as <| "Z"->1|>

Keys...[[1]] returns the "key" to the only item in the association, that of the least used character. ("Z" in the present case)

#~Position~... returns then position of the key in the original matrix, #.


3

Perl 5 -p00, 52 45 bytes

/^(.)(\1*
)*(\1*)|^/;$_=$&=~y/
//.$".length$3

45 bytes

52 bytes

How

  • -p00 : like -n but also print, paragraph mode
  • /^(.)(\1* )*(\1*)|^/ : matches either
    • from start $1: first character, $2: repetition (not used), $3: characters before the "needle" in the line, $& whole match
    • or null string (position 0) no capture.
  • $_= : to assign the default input/argument variable
  • so $&=~y/ // the number of newlines of $&
  • .$". : concatenate with $" (space character by default) and concatenate
  • length$3 : the length of $3

3

R 42 bytes

function(m)which(ave(m,m,FUN=length)==1,T)

Try it online!

Input: a haystack matrix m

Output: (row,col) vector - index starting at 1


1
Nice job, and welcome to PPCG! I believe this is 42 bytes, since the f= can be omitted from the byte count, but not the function(m)=.
BLT

@BLT I wasn't sure about that but thanks for the heads up :)
niko




2

PowerShell, 107 98 82 77 bytes

$l=@{}
$args|%{if($_-10){$l.$_+=$x++,+$y}else{$x=0;++$y}}
$l|% v*|? c*t -eq 2

Try it online!

Takes a splatted string with LFs. Returns zero-indexed location x,y. Unrolled:

$locations=@{}                      # make a hashtable. key=char, value=location array
$args|%{
    if($_-10){                      # if current char is not LF
        $locations.$_+=$x++,+$y     # add $x,$y to hashtable value and move $x to next pos
    }else{
        $x=0;++$y                   # move $x,$y to next line
    }
}
$locations|% Values|? Count -eq 2   # find and output location array with 2 elements (x,y)

1

Python 3, 93 bytes

def f(s):x=s.find("\n")+1;return[(i%x,i//x)for i,c in enumerate(s)if s.count(c)<2and" "<c][0]

Try it online!

Input is taken as a multiline string. Output is 0-indexed



1

Retina 0.8.2, 41 bytes

s`(?=(.)+\1)(.*?¶)*(.*)(?!\1|¶).+
$.3,$#2

Try it online! 0-indexed. Explanation:

s`

Allow . to match newlines. This costs 3 bytes (3rd byte is the ? before the ) but saves 6 bytes.

(?=(.)+\1)

Look ahead for two identical characters. \1 then becomes the hay.

(.*?¶)*

Count the number of newlines before the needle.

(.*)

Capture the hay to the left of the needle.

(?!\1|¶)

Ensure that the needle isn't hay or a newline.

.+

Match the rest of the hay so that the result replaces it.

$.3,$#2

Output the width of the left hay and the number of newlines.


1

C# (Visual C# Interactive Compiler), 82 bytes

x=>w=>{int y=x.IndexOf(x.GroupBy(c=>c).Last(g=>g.Count()<2).Key);return(y%w,y/w);}

Thanks to dana for shaving off 6 bytes!

Try it online!

Old solution, 106 bytes

n=>m=>{var z=n.Distinct();int d=n.IndexOf(n.Count(c=>c==z.First())>1?z.Last():z.First());return(d%m,d/m);}

Both take input as a string and an integer specifying the amount of columns.

Try it online!


@dana never knew that Enumerable.Last() accepted a delegate, thanks
Embodiment of Ignorance

1

Java 8, 104 Bytes

(x,w)->{int i=0,p=x.length;for(;i<p;i++)if(x[i]!=x[(i+1)%p]&&x[i]!=x[(i+2)%p])break;return i/w+","+i%w;}

Input is array of char, and integer indicating row width.

Output is zero-based, vertical then horizontal (i.e., row number then column number)

Explanation:

(x,w)->{
    int i=0, p=x.length;
    for (;i<p;i++)          //iterate through characters in x
      if (x[i]!=x[(i+1)%p] && x[i]!=x[(i+2)%p])    //compare x[i] with the two subsequent characters in array, wrapping around if necessary
        break;
    return i/w+","+i%w;}  //return row number then column number, zero-based

1

Python 3, 93 89 85 58 bytes

Complete rewrite taking input as concatenated string, width:

lambda g,w:divmod(g.index({g.count(c):c for c in g}[1]),w)

Try it online!


Original answer:

def k(g):t=''.join(g);return divmod(t.index({t.count(c):c for c in t}[1]),len(g[0]))

EDIT: Saved 4 bytes by swapping linebreak/indent for semicolons. Saved another 4 bytes by using divmod(thanks @JonathanFrech).

Try it online!

I know this could be a lot shorter, but I just wanted to try an approach around this dict comprehension.


1
Using divmod would save five bytes.
Jonathan Frech

0

MATL, 11 bytes

tX:YmyYk-&f

Output is row, then column; 1-based.

Try it online!

Explanation

t    % Implicit input. Duplicate
X:   % Linearize into a column
Ym   % Compute mean (characters are converted to ASCII codes)
y    % Duplicate from below: pushes input again
Yk   % Closest value: gives the input value that is closest to the mean
-    % Subtract, element-wise. Gives non-zero for the value farthest from the mean
&f   % Two-output find: gives row and column indices of nonzeros. Implicit display

0

Pyth, 15 14 12 bytes

.Dxz-zh.-z{z

Takes input as the length of the row and the input without lines and outputs as [row, column].
Try it here

Explanation

.Dxz-zh.-z{z
       .-z{z    Subtract one of each character from the input.
      h         Take the first.
    -z          Remove all instances from the input.
  xz            Find the remaining character in the input.
.D          Q   Take the result divmod the (implicit) length of the row.

Old approach

mxJmt{kdeSJ.TB

Try it here

Explanation

mxJmt{kdeSJ.TB
           .TBQ   Take the (implicit) input and its transpose...
m      d          ... and for each...
   mt{k           ... deduplicate each row...
 xJ     eSJ       ... and find the index of the largest.     

0

Charcoal, 40 bytes

≔§⎇⌕θ§θ¹ηθ⁰ζSθW⁼№θζLθ«⊞υωSθ»I⌕Eθ⁼ιζ⁰,ILυ

Try it online! Link is to verbose version of code. I must be doing something wrong because this is almost as long as the Retina answer. Explanation:

≔§⎇⌕θ§θ¹ηθ⁰ζ

Check whether the second character in the first string is also the first character, and take the first character of the first string if so otherwise the first character of the second string if not. This is then the hay.

SθW⁼№θζLθ«⊞υωSθ»

Keep reading strings until a string whose hay is less than its length is found.

I⌕Eθ⁼ιζ⁰,ILυ

Output the position of the mismatching element and then the number of strings previously read.


0

MATLAB, 68 22 bytes

[r,c]=find(v~=v(1));if size(r,1)>1 disp([1,1]);else disp([r,c]);end;

If I could exclude any one case, such as [1,1] in this solution, I could have saved several bytes.

Updated solution:

@(v)find(v-mode(v(:)))

Thanks to @sundar for helping me with the special case problem and saving 42 bytes! Also, thanks to @Luis_Mendo for the suggestions and saving me another 2 bytes!


I think you can get rid of the check for [1,1] case by using mode(v(:)) instead of v(1).
sundar - Reinstate Monica

You need to wrap your code so that it is a full program or a function; you cannot assume that the input is in a variable v. Also, you can probably replace ~= by -, and remove the final ;
Luis Mendo

0

Röda, 81 bytes

f a{i=indexOf;l=i("
",a)+1;chars a|sort|count|[[_2,_1]]|min|i _[1],a|[_%l,_1//l]}

Try it online!

Takes input as a string containing newline-terminated lines. Returns a stream containing 0-indexed horizontal and vertical indexes.

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.