Marquee sign letters

41

3

Each day you put up a new word on a marquee sign with movable letters, buying just the letters you need to write it. You re-use letters you've bought for earlier words whenever possible. Given the words you want to write each day in order, output the letters you buy each day.

Example

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

Day 1: You start with no letters, so to write ONE, you buy all its letters E, N, O.
Day 2: The next day, you want to put up TWO (taking down the ONE). You already have an O from ONE, so you buy an additional TW.
Day 3: At this point, you have ENOWT. To write THREE, you need EHR. Note that you need to buy a second E in addition to the one you have.
Day 4: To write SEVENTEEN, you need 4 E's total of which you already have two (not three!), so you buy two more. You also have the T and one of the N's, so you buy the remaining letters: EENSV.

We've output letters sorted alphabetically in this example, but you may output them in any order.

Input: A non-empty list of non-empty strings of letters A-Z. You may use lowercase if you prefer. Lists of characters are fine for strings.

Output: Output or print the additional letters you need to buy each day. The letters for a day may be output in any order, but the days must come in the right order.

The letters from each day should be separated from other days so you can tell where a day ends. A trailing and/or leading separator is fine, both within a day or between days. Note that a day may have no letters bought, which should be reflected in the output (a space or empty line is OK, even for the last day).

Test cases

['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', '', '']

Here are all the inputs and outputs as separate lists:

[['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', '', '']]

And as space-separated strings (the trailing spaces in the outputs matter):

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  

Leaderboards

var QUESTION_ID=183544,OVERRIDE_USER=20260;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

xnor

Posted 2019-04-21T15:06:00.503

Reputation: 115 687

5A wild leaderboard script has appeared in the userscript age :o – Quintec – 2019-04-21T21:50:46.740

Can we output as an an array of characters that need to be bought rather than a string of all the characters? e.g.: [['E', 'N', 'O'], ...] – Downgoat – 2019-04-22T06:28:44.400

Is the output SHORTLONGOOOOO valid for the last output? AKA using no delimiters? – Magic Octopus Urn – 2019-04-22T18:15:16.350

@Downgoat Yes, lists are chars are fine to output. – xnor – 2019-04-22T21:23:13.687

@MagicOctopusUrn No, you need delimiters, otherwise you can't tell what letters are for what day. – xnor – 2019-04-22T21:23:46.387

Can the input be a space-delimited string? Your last code block implies(?) that it can be. – Tau – 2019-04-24T13:32:23.087

@Tau Yes, space separated is fine. – xnor – 2019-04-25T05:36:19.893

Answers

10

Haskell, 54 49 bytes

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

Try it online!

We build the output list by calculating pairwise the list difference (\\) of the input list and the cumulative append of the output list (starting with "").

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

With both Data.List and Data.Function in scope (e.g. by using the lambdabot environment), this can be shortened to 30 bytes:

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

Edit: -5 bytes thanks to @Sriotchilism O'Zaic.

nimi

Posted 2019-04-21T15:06:00.503

Reputation: 34 639

Why not this? – Post Rock Garf Hunter – 2019-04-22T17:48:47.180

10

Python 2, 72 68 bytes

-4 bytes thanks to Jonathan Allan.

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

Try it online!

Commented

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

ovs

Posted 2019-04-21T15:06:00.503

Reputation: 21 408

3for r in input(): saves 4 bytes. – Jonathan Allan – 2019-04-22T01:03:43.580

8

Jelly, 7 bytes

,œ-@Kɗ/

Try it online!

Output: -separated string.

Erik the Outgolfer

Posted 2019-04-21T15:06:00.503

Reputation: 38 134

7

Perl 6, 44 40 bytes

-4 bytes thanks to Matthew Jensen

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

Try it online!

Outputs as a list of lists of characters.

Explanation

{                                  } # Anonymous codeblock
 $!=@;                               # Initialise $! to an empty list
      .map:{                      }  # Map each item in the input to
                    .comb            # The string split to characters
                                     # 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

Jo King

Posted 2019-04-21T15:06:00.503

Reputation: 38 234

2A reason for the downvote would be appreciated – Jo King – 2019-04-21T18:38:50.617

Not the downvoter, but I'm gonna say this output format strays too far. Something like Bag(E(2), N, S, V) would need to actually show two E's to be OK. – xnor – 2019-04-21T18:59:12.327

3What, really? That's just the default print formatting. The return result is an unordered list that contains those characters (and can contain multiple of the same character). I'll update the output formatting to better reflect this, but the downvote seems ridiculous. – Jo King – 2019-04-21T19:15:19.123

Downvoter, could you please explain, is this about I/O or something else? About the bag format, I don't know Perl, is this common for I/O in Perl golfs? Looking at the docs (cached because site is down), they seem to me to be more like dicts with counts, akin to Python's collections.Counter which I didn't intend to allow as output. Can one easily iterate over bag elts with multiplicity, cast to a list/array, display with multiplicity, etc?

– xnor – 2019-04-21T20:06:26.000

3Downvote was a mistake, was meant to be up. – Jonathan Allan – 2019-04-22T00:28:14.113

@xnor I've changed the output to a list of list of characters at the expense of 6 bytes – Jo King – 2019-04-22T02:24:47.907

I don't know how Perl works, but I was playing around and removing .Bag seems not to change the function. – Matthew Jensen – 2019-12-10T00:09:01.240

@MatthewJensen You are correct, since the operator with a Bag on one side converts the other side to a Bag as well. Thanks! – Jo King – 2019-12-10T02:21:19.880

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']))

tsh

Posted 2019-04-21T15:06:00.503

Reputation: 13 072

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

– Arnauld – 2019-04-22T07:45:00.550

7

Haskell, 44 bytes

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

Try it online!

Output is a string like ONE,TW,HRE,SVEEN with commas between days.

Lynn

Posted 2019-04-21T15:06:00.503

Reputation: 55 648

1What a nice use of the output format to avoid needing to fold the \\. And an unexpected foldl1 base case too. – xnor – 2019-04-27T03:43:37.540

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: }.@>.

Jonah

Posted 2019-04-21T15:06:00.503

Reputation: 8 729

[:}.@>|.(],a.<@#~0>.-&(1#.a.=/;))&.>/@,<@a: – FrownyFrog – 2019-04-22T15:28:27.903

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

As far as I can tell, sorting is nowhere in the requirements. – FrownyFrog – 2019-04-22T21:10:44.627

2Updated and now that I've had time to absorb it, just wanted to say again: That's damn nice J! – Jonah – 2019-04-23T03:12:14.317

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()

Arnauld

Posted 2019-04-21T15:06:00.503

Reputation: 111 334

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!

Neil A.

Posted 2019-04-21T15:06:00.503

Reputation: 2 038

You can do #define v std::vector<std::string and remove using namespace std to reduce byte count by 6 bytes. – anatolyg – 2019-04-22T15:31:12.477

2

Python 2, 102 100 bytes

from collections import*
c=Counter
l=c()
for x in map(c,input()):y=x-l;l+=y;print list(y.elements())

Try it online!

-2 bytes, thanks to Embodiment of Ignorance

TFeld

Posted 2019-04-21T15:06:00.503

Reputation: 19 246

100 bytes – Embodiment of Ignorance – 2019-04-23T02:09:21.183

@EmbodimentofIgnorance Thanks :) – TFeld – 2019-04-23T09:21:02.683

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

Shaggy

Posted 2019-04-21T15:06:00.503

Reputation: 24 623

1@Downvoter, please have the decency to leave a comment. – Shaggy – 2019-04-22T16:18:14.123

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;
}

dana

Posted 2019-04-21T15:06:00.503

Reputation: 2 541

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.

qdread

Posted 2019-04-21T15:06:00.503

Reputation: 419

Welcome! You can (and should if possible) post a link to https://tio.run/#r; if you open it, you'll notice it automatically pre-create the post with the bytes count header, the code etc ;)

– digEmAll – 2019-04-23T12:33:40.040

Unfortunately vecsets is not included in TIO :( – digEmAll – 2019-04-23T12:34:27.407

@digEmAll thanks for the tip. Is it considered bad form to use functions from packages? I thought about hard coding the vsetdiff but it would have wasted too many bytes. – qdread – 2019-04-23T14:11:48.900

1no, 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 – 2019-04-23T16:10:12.143

1103 in base R – digEmAll – 2019-04-24T06:43:34.397

1Your version in 99 bytes – digEmAll – 2019-04-24T06:55:22.043

180 if we print the values instead of storing – digEmAll – 2019-04-24T06:58:43.343

@digEmAll these are great! nice to see what's possible. :-D Didn't realize you could nest scan() but I guess it's obvious – qdread – 2019-04-24T12:32:02.863

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.

AdmBorkBork

Posted 2019-04-21T15:06:00.503

Reputation: 41 581

1

05AB1E, 11 bytes

-6 thanks to Kevin Cruijssen

ćsvDysSõ.;»

Try it online!

Magic Octopus Urn

Posted 2019-04-21T15:06:00.503

Reputation: 19 422

1

Your 15-byter works, but I would replace the trailing J with ». Also, you can save 4 bytes by replacing vyð.;}ðK with Sõ.; 11 bytes.

– Kevin Cruijssen – 2019-04-23T08:29:39.860

Ahhhh... I needed S to make it vectorize. – Magic Octopus Urn – 2019-04-24T12:34:42.943

1

Red, 75 bytes

func[b][a: copy""foreach w b[foreach c a[replace w c""]print w append a w]]

Try it online!

Galen Ivanov

Posted 2019-04-21T15:06:00.503

Reputation: 13 815

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.

william porter

Posted 2019-04-21T15:06:00.503

Reputation: 331

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.

LambdaBeta

Posted 2019-04-21T15:06:00.503

Reputation: 2 499

106 bytes – ceilingcat – 2019-04-25T01:19:04.820

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.

Roman Podymov

Posted 2019-04-21T15:06:00.503

Reputation: 151

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
}

sprague44

Posted 2019-04-21T15:06:00.503

Reputation: 81

1

PHP, 87 bytes

for(;$w=$argv[++$i];print' ')for($b=$a;$l=$w[$$i++];)$b[$l]?$b[$l]--:++$a[$l]&&print$l;

Try it online!

Night2

Posted 2019-04-21T15:06:00.503

Reputation: 5 484

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

Neil

Posted 2019-04-21T15:06:00.503

Reputation: 95 035

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;}

rexkogitans

Posted 2019-04-21T15:06:00.503

Reputation: 589

0

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

a=>{var b="";for(int i=0;;b+=a[i++])foreach(var z in b)if(a[i].Contains(z))a[i]=a[i].Remove(a[i].IndexOf(z),1);}

Try it online!

Embodiment of Ignorance

Posted 2019-04-21T15:06:00.503

Reputation: 7 014

Hmm... This throws an exception? – dana – 2019-04-23T13:53:36.617

@dana I'm pretty sure functions that don't return anything are allowed to exit with exceptions – Embodiment of Ignorance – 2019-04-24T03:48:19.897

Interesting... I suppose it's not the strangest rule. – dana – 2019-04-24T04:03:34.447

0

Perl 5 -p, 28 bytes

for$i(@h){s/$i//}push@h,/./g

Try it online!

Xcali

Posted 2019-04-21T15:06:00.503

Reputation: 7 671

0

Ruby, 52 bytes

->l{r="";l.map{|x|r.chars{|c|x[c]&&x[c]=''};r+=x;x}}

Try it online!

G B

Posted 2019-04-21T15:06:00.503

Reputation: 11 099

0

K (ngn/k), 36 33 bytes

*+(){(a;x,a:&0|-/#''='(y;x@:1))}\

Try it online!

ngn

Posted 2019-04-21T15:06:00.503

Reputation: 11 449

0

Stax, 7 bytes

é█üa%┐┤

Run and debug it

Output is newline separated.

recursive

Posted 2019-04-21T15:06:00.503

Reputation: 8 616