Lettere del segno di selezione


41

Ogni giorno inserisci una nuova parola su un segno di selezione con lettere mobili , acquistando solo le lettere necessarie per scriverlo. Riutilizzi le lettere che hai acquistato per parole precedenti ogni volta che è possibile. Date le parole che vuoi scrivere ogni giorno in ordine, pubblica le lettere che acquisti ogni giorno.

Esempio

Input:  ['ONE', 'TWO', 'THREE', 'SEVENTEEN']
Output: ['ENO', 'TW', 'EHR', 'EENSV']

Giorno 1: Si inizia con nessuna lettera, in modo di scrivere ONE, di acquistare tutte le sue lettere E, N, O.
Giorno 2: il giorno successivo, si desidera mettere su TWO (abbattendo il ONE). Hai già un Oda ONE, quindi ne acquisti un altro TW.
3 ° giorno: a questo punto, hai ENOWT. Per scrivere THREE, è necessario EHR. Nota che è necessario acquistare un secondo Ein aggiunta a quello che hai.
Giorno 4: per scrivere SEVENTEEN, hai bisogno Edel totale di 4 di cui ne hai già due (non tre!), Quindi ne acquisti altri due. Hai anche il Te uno dei N, quindi acquisti le lettere rimanenti: EENSV .

In questo esempio abbiamo emesso lettere in ordine alfabetico, ma puoi produrle in qualsiasi ordine.

Input: un elenco non vuoto di stringhe di lettere non vuote A-Z. Puoi usare lettere minuscole se preferisci. Gli elenchi di caratteri vanno bene per le stringhe.

Output: stampa o stampa le lettere aggiuntive che devi acquistare ogni giorno. Le lettere per un giorno possono essere emesse in qualsiasi ordine, ma i giorni devono arrivare nell'ordine giusto.

Le lettere di ogni giorno devono essere separate dagli altri giorni in modo da poter sapere dove finisce un giorno. Un separatore finale e / o iniziale va bene, sia entro un giorno che tra i giorni. Si noti che un giorno potrebbe non avere lettere acquistate, il che dovrebbe riflettersi nell'output (uno spazio o una riga vuota è OK, anche per l'ultimo giorno).

Casi test

['ONE', 'TWO', 'THREE', 'SEVENTEEN']
['ENO', 'TW', 'EHR', 'EENSV']

['ONE', 'TWO', 'ONE', 'THREE']
['ENO', 'TW', '', 'EHR']

['ABC', 'AABC', 'ABBC', 'ABCC', 'AABBCC']
['ABC', 'A', 'B', 'C', '']

['SHORT', 'LOONG', 'LOOOONG', 'LOOOOOOONG', 'SHORT', 'LOOONG']
['HORST', 'GLNO', 'OO', 'OOO', '', '']

Ecco tutti gli ingressi e le uscite come elenchi separati:

[['ONE', 'TWO', 'THREE', 'SEVENTEEN'], ['ONE', 'TWO', 'ONE', 'THREE'], ['ABC', 'AABC', 'ABBC', 'ABCC', 'AABBCC'], ['SHORT', 'LOONG', 'LOOOONG', 'LOOOOOOONG', 'SHORT', 'LOOONG']]
[['ENO', 'TW', 'EHR', 'EENSV'], ['ENO', 'TW', '', 'EHR'], ['ABC', 'A', 'B', 'C', ''], ['HORST', 'GLNO', 'OO', 'OOO', '', '']]

E come stringhe separate da spazio (gli spazi finali nelle uscite contano):

ONE TWO THREE SEVENTEEN
ONE TWO ONE THREE
ABC AABC ABBC ABCC AABBCC
SHORT LOONG LOOOONG LOOOOOOONG SHORT LOOONG

ENO TW EHR EENSV
ENO TW  EHR
ABC A B C 
HORST GLNO OO OOO  

Classifiche


5
Uno script di classifica selvaggio è apparso nell'era utenti: o
Quintec il

Possiamo produrre come una matrice di caratteri che devono essere acquistati anziché una stringa di tutti i personaggi? ad es .:[['E', 'N', 'O'], ...]
Downgoat,

L'output è SHORTLONGOOOOOvalido per l'ultimo output? AKA non usa delimitatori?
Magic Octopus Urn

@Downgoat Sì, gli elenchi sono caratteri vanno bene per l'output.
xnor

@MagicOctopusUrn No, hai bisogno di delimitatori, altrimenti non puoi dire quali lettere sono per quale giorno.
xnor

Risposte:


10

Haskell, 54 49 byte

import Data.List
g x=zipWith(\\)x$scanl(++)""$g x

Provalo online!

Costruiamo l'elenco di output calcolando in modo accoppiato la differenza di elenco ( \\) dell'elenco di input e l'appendice cumulativa dell'elenco di output (a partire da "").

input list:                ONE       TWO       THREE        SEVENTEEN
cumulative append:         ""   +->  ONE  +->  ONETW   +->  ONETWHRE
list difference (output):  ONE -+    TW  -+    HRE    -+    SVEEN

Con entrambi Data.Liste Data.Functionnell'ambito (ad esempio utilizzando l'ambiente lambdabot), questo può essere ridotto a 30 byte:

fix.(.scanl(++)"").zipWith(\\)

Modifica: -5 byte grazie a @Sriotchilism O'Zaic.



10

Python 2 , 72 68 byte

-4 byte grazie a Jonathan Allan.

p=''
for r in input():
 for x in p:r=r.replace(x,'',1)
 print r;p+=r

Provalo online!

Commentate

l=input()       # the list of words to write
p=''            # p contains all letters we own
for r in l:     # for each word ...
  for x in p:   # for each letter we own ...
    r=r.replace(x,'',1)   # remove one occurence from the current word
  print r       # print the remaining word
  p+=r          # add the remaining chars to p

3
for r in input():salva 4 byte.
Jonathan Allan il


7

Perl 6 , 44 byte

{$!=@;.map:{kxxv $!=.comb.Bag∖($⊎=$!):}}

Provalo online!

Emette come un elenco di elenchi di caratteri.

Spiegazione

{                                      } # Anonymous codeblock
 $!=@;                                   # Initialise $! to an empty list
      .map:{                          }  # Map each item in the input to
                    .comb                # The string split to characters
                         .Bag            # In a Bag
                                        # Set minus
                              ($⊎=$!)    # The accumulated Bag of results
                 $!=                     # And save the result for the next item
            kxxv                     : # Then decompose the Bag into a list

2
Un motivo per il downvote sarebbe apprezzato
Jo King il

Non il downvoter, ma sto per dire che questo formato di output si allontana troppo. Qualcosa del genere Bag(E(2), N, S, V)dovrebbe effettivamente mostrare due E per essere OK.
xnor

3
Cosa veramente? Questa è solo la formattazione di stampa predefinita. Il risultato restituito è un elenco non ordinato che contiene quei caratteri (e può contenere multipli dello stesso carattere). Aggiornerò la formattazione dell'output per riflettere meglio questo, ma il downvote sembra ridicolo.
Jo King,

Downvoter, potresti spiegare, si tratta di I / O o qualcos'altro? Per quanto riguarda il formato della borsa, non conosco il Perl, è comune per l'I / O nei golf Perl? Guardando i documenti (memorizzati nella cache perché il sito non funziona), mi sembrano più simili a dicts con conteggi, simili a quelli di Python collections.Counterche non intendevo consentire come output. Si può iterare facilmente su elts bag con molteplicità, eseguire il cast in un elenco / array, visualizzare con molteplicità, ecc.?
xnor

3
Il downvote è stato un errore, doveva essere in crescita.
Jonathan Allan il

7

Haskell , 44 byte

import Data.List
foldl1(\a x->a++',':(x\\a))

Provalo online!

L'output è una stringa simile ONE,TW,HRE,SVEENalle virgole tra i giorni.


1
What a nice use of the output format to avoid needing to fold the \`. And an unexpected foldl1` base case too.
xnor

7

JavaScript (Node.js), 59 bytes

a=>a.map(h=>([...t].map(c=>h=h.replace(c,'')),t+=h,h),t='')

Try it online!

Quite straightforward solution. For each word h, remove letters we already have.

Here is an explained version of that code:

f = list => {
  // the string that accumulates all the letters already bought
  let accu = '';
  // for every word in the list
  return list.map( word => {
    // for every letter already bought 
    [...accu]
      // remove the letter from the word
      .map(char => {
        return word = word.replace(char,'')
      });
    // add not bought letters to accumulator
    accu += word;
    // the reduced word (without already bought letters) should be added to result map
    // this represents the letters to buy today
    return word
  }, accu)
}

console.log(f(['ONE', 'TWO', 'THREE', 'SEVENTEEN']))
console.log(f(['ONE', 'TWO', 'ONE', 'THREE']))
console.log(f(['ABC', 'AABC', 'ABBC', 'ABCC', 'AABBCC']))
console.log(f(['SHORT', 'LOONG', 'LOOOONG', 'LOOOOOOONG', 'SHORT', 'LOOONG']))


You can save 1 byte by borrowing the only worthwhile trick from my otherwise overcomplicated solution.
Arnauld

5

J, 29 bytes

-29 bytes thanks to FrownyFrog!

(],a.<@#~0>.-&(1#.a.=/;))/@|.

Try it online!

Original Post

J, 58 bytes

[:}.@>[:(],<@(/:~@({.@>@-.&(((e.<@#[){:)\));))&.>/<@a:,~|.

Try it online!

Thanks to ngn for help improving the "subtract letters while respecting repetition part".

Not a great fit for J, but an illuminating exercise.

Let's begin by constructing a helper verb wo ("without") that removes all chacters in one string from another, while respecting repetitions.

wo=.{.@>@-.&(((e. <@# [) {:)\)

There is a fun idea here: We make each repeated instance of a character unique, by repeating it the required number of times. Thus if our original string is ABBA it becomes:

┌─┬─┬──┬──┐
│A│B│BB│AA│
└─┴─┴──┴──┘

A third A would become AAA and so on. This is accomplished by the phrase ((e. <@# [) {:)\, which takes each prefix \, looks at the final element {: of it, and constructs a mask of all elements in that prefix that match e. that final element, and then filters and boxes just those elements <@#.

With our inputs both "unique-ified" we can now safely use normal set minus -. while still respecting repetition.

We then open each result and take only the first element to "undo" our repetitions: {.@>

Plugging this helper verb in, our overall solution (which simply inlines it) becomes:

[: }.@> [: (] , <@(/:~@wo ;))&.>/ <@a: ,~ |.

Essentially, all we do here is setup our problem as a single reduction. We start be reversing the input |. and appending to it ,~ an ace a:, or empty box, which will be the initial value of our final result, like so:

┌─────────┬─────┬───┬───┬──┐
│SEVENTEEN│THREE│TWO│ONE│┌┐│
│         │     │   │   ││││
│         │     │   │   │└┘│
└─────────┴─────┴───┴───┴──┘

We stick the following verb between each element to effect the reduction:

(] , <@(/:~@wo ;))/

This says: take the right input ] (ie, our result) and append to it , the left input (this is ONE on the first iteration, TWO on the 2nd, etc) without wo the raze of ; the right input (ie, without any previous letters so far used), but before appending sort it /:~ and box it again <@.

At the end of all this we'll have the result we want, a list of boxes, but all inside one big additional box, and still with the empty box at the front. Thus we open to remove the outer box and kill the first element: }.@>.


[:}.@>|.(],a.<@#~0>.-&(1#.a.=/;))&.>/@,<@a:
FrownyFrog

A simple (],a.<@#~0>.-&(1#.a.=/;))/@|. also works unless I'm missing an edge case.
FrownyFrog

As far as I can tell, sorting is nowhere in the requirements.
FrownyFrog

2
Updated and now that I've had time to absorb it, just wanted to say again: That's damn nice J!
Jonah

4

JavaScript (ES6),  66  65 bytes

a=>a.map(b=s=>[...s].filter(c=>x==(x=x.replace(c))?b+=c:0,x=b+0))

Try it online!

Commented

b is a string holding all available letters (and also some invalid characters, but this is irrelevant to the algorithm). For each new word, we create a copy of b in x. Each letter c of a word is either used by removing it from x or bought by appending it to b. Only bought letters are returned.

a =>                      // a[] = input
  a.map(b =               // initialize b to the callback function of this map()
                          // it will be coerced to a string that does not contain
                          // any letter in uppercase
    s =>                  // for each entry s in a[]:
    [...s].filter(c =>    //   for each character c in s:
      x == (              //     check whether x is changed when
        x = x.replace(c)  //     c is replaced with 'undefined'
      ) ?                 //     if so:
        b += c            //       append c to b and keep c
      :                   //     else:
        0,                //       discard c
      x = b + 0           //     coerce b to a string and save it in x
    )                     //   end of filter()
  )                       // end of map()

4

C++ (gcc), 177 170 bytes

-5 bytes thanks to @anatolyg's tip, -2 bytes to small things I noticed.

#import<random>
#define v std::vector<std::string>
v a(v p){std::vector<int>o(91),b;int j=-1;for(auto i:p){b=o;p[++j]="";for(int c:i)--b[c]<0?p[j]+=c,++o[c]:0;}return p;}

Explanation

#import<random> adds both <string> and <vector> for half the bytes.

First creates a 91-element vector of 0s (only indices 65-90 are used to store letter occurences), and another vector of the same type but not set to a value. Iterates through each element of the input (the days): gets the currently owned letters, gets the letters that are needed for the day, overrides the input at the index with the needed amount and updates the owned letters. Returns the overridden input.

Try it online!


You can do #define v std::vector<std::string and remove using namespace std to reduce byte count by 6 bytes.
anatolyg

2

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

a=>{var b="";for(dynamic i=0,e,f;i<a.Count;b+=a[i++]=f)foreach(var c in((e,f)=(b.ToList(),"")).f+a[i])f+=e.Remove(c)?"":c;}

Try it online!

Anonymous function that outputs by modifying an input array.

// a: input array of strings
a=>{
  // b: cumulative letters
  var b="";
  for(
    // i: loop index of string
    // e: copy of cumulative letters for manipulation
    // f: characters missing from current string
    dynamic i=0,e,f;
    // iterate over each string in a
    i<a.Count;
    // add missing letters of the day to
    // cumulative missing letters and
    // update array for output
    b+=a[i++]=f
  )
    // iterate current string with character c
    foreach(var c in
      // tuplized variable assignment
      // e=b.ToList()
      //   set e to a copy of the cumulative letters
      // f=""
      //   initially there are no letters needed for the day
      ((e,f)=
      (b.ToList(),"")).f+a[i]
    )
      // conditionally add c to missing letters for the day
      f+=e.Remove(c)?"":c;
}

2

R, 119 112 106 103 bytes

-7 bytes from aliasing the two longer function names and now taking user input from scan()
-6 bytes to only call strsplit() once at the beginning
-3 bytes to get rid of the aliasing again and assign two variables in one call

(Also edited the byte count which was erroneously low earlier)

a=scan(,'');b=a=strsplit(a,'');for(i in 2:length(a))b[[i]]=vecsets::vsetdiff(a[[i]],unlist(b[1:i-1]));b

This is my very first PPCG submission of any kind! So I have no idea what I'm doing both in terms of golfing and in terms of posting etiquette. The output is a list of vectors which may or may not meet the terms of the challenge. :-P

As for the code itself, it takes user input via scan() and compares each new day's letters to the cumulatively owned letters, as in other solutions. If there are shorter alternatives to unlist and strsplit for converting strings into vectors of individual characters that would be cool to know. I also used the vsetdiff function in Carl Withoft's vecsets package to get the set difference of the letters needed for the next day and the current letters owned.


1
no, it's perfectly fine. I'm a little reluctant myself in using external packages, but it's just me... I prefer to approach the challenges in base R code ;)
digEmAll






2

PowerShell, 71 bytes

$args|%{$w=$_;$p|% t*y|%{$w=$w-replace"^(.*?)$_(.*)",'$1$2'};$w;$p+=$w}

Try it online!

Takes input words $args and iterates over them. Each iteration we set the current word $w, then loop over our $pool of already-purchased letters. Each inner loop, we perform a regex -replace on our current $word, so that we're replacing just the first instance of the letter from our $pool. Once we've gone through all letters in the pool, we output what's remaining $w (i.e., what we need to purchase), and then tack those letters onto our pool $p+=$w for the next word.


2

Japt, 15 14 bytes

£Q®X=rZPPÃQ±XX

Try it

£Q®X=rZPPÃQ±XX     :Implicit input of array
£                  :Map each X
 Q®                :  Map each Z in Q (initially a quotation mark)
   X=              :    Reassign to X
     rZ            :    Replace Z with
       P           :    The empty string
        P          :    With the default global flag disabled
         Ã         :  End map
          Q±X      :  Append X to Q
             X     :  Return X

1
@Downvoter, please have the decency to leave a comment.
Shaggy


1

Excel VBA, 127 bytes

Function z(w)
z=""
For Each x In w.Cells
v=x.value
For y=1To Len(z)
v=Replace(v,Mid(z,y,1),"",1,1)
Next
z=z&v
Next
End Function

Takes input in the form of an excel range.


1

C (gcc), 118 bytes

m(a,r,q,u)char**a,*r,*q,*u;{for(;*a;a++,memcpy(r,q,255))for(memcpy(q,r,255),u=*a;*u;u++)*u=r[*u]-->0?32:(q[*u]++,*u);}

Try it online!

As a little bonus it takes the stock in r at the start as an array. Outputs the input null-terminated null-terminated-string list a with all pre-owned letters replaced with spaces.




1

Swift 4.2/Xcode 10.2, 244 242 239 238 bytes

a.reduce(([Character:Int](),[String]())){c,l in let b=l.reduce(into:[Character:Int]()){$0[$1,default:0]+=1}.map{($0,max(0,$1-(c.0[$0] ?? 0)))};return(c.0.merging(b){$0+$1},c.1+[b.map{String(Array(repeating:$0.0,count:$0.1))}.joined()])}.1

Try it online!

The letters are not arranged in alphabetical order, it is not forbidden by the rules.


1

Scala, 68 bytes

(c:Seq[String])=>c./:(Seq(""))((a,n)=>a:+n.diff(a./:("")(_+_))).tail

Try it online!

/: is short-hand for foldLeft operator, a is aggregation, ultimately returns the result we want, n is next element

Un-golfed

def NewLettersPerDay(c: Seq[String]): Seq[String] = {
    c.foldLeft(Seq(""))((agg, next) => {
      val existingLetters = agg.reduce(_+_)
      val newDayLetters = next.diff(existingLetters)
      agg :+ newDayLetters
    }).tail
}


0

Charcoal, 18 bytes

EθΦι¬⊙…θκ‹№…ιμλ№νλ

Try it online! Link is to verbose version of code. Explanation:

 θ                  Input array
E                   Map over strings
   ι                Current string
  Φ                 Map over characters
       θ            Input array
      …             Truncated to length
        κ           Outer index
    ¬               Logical Not
     ⊙              Any element exists where
          №         Count of
              λ     Current letter in
            ι       Outermost word
           …        Truncated to
             μ      Current letter index
         ‹          Is less than
               №    Count of
                 λ  Current letter in
                ν   Innermost word
                    Implicitly print each day's bought letters on their own line

0

PHP, UTF-8 aware (253 bytes)

<?php $p=[];for($i=1;$i<$argc;$i++){$a=$p;$b=[];for($j=0;$j<mb_strlen($s=$argv[$i]);$j++){$k=1;if(isset($a[$c=mb_substr($s,$j,1)]))if($a[$c]){$k=0;$a[$c]--;}if($k){echo $c;if(isset($b[$c]))$b[$c]+=$k;else $b[$c]=$k;}}$p=array_merge($p,$b);echo PHP_EOL;}





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.