Creating words by structure

4

Context

As a conlanger, I am interested in creating a uniform, naturalistic language. One of the tricks is to create vocabulary according to certain structures of words. An example from English: In English, we have the word “tap” structured consonant-vowel-consonant. Usually, this means that there are many other words of this structure: “cat”, “dog”, “rock”, “fog”, “good”, etc.

Task

As input, you have:

  • an array C containing strings: consonants (C is the first letter in the word consonants). Identical consonants cannot be repeated on this list. For example, this list cannot contain ['b', 'b'].
  • an array V containing strings: vowels (V is the first letter of the word vowels). Identical vowels cannot be repeated on this list.
  • string S, which contains something like this "CVCCV" (any combination of "C" and "V")

Your task is to replace “C” in the string with a randomly taken string from array C and replace “V” in the string with a randomly taken string from array V and return (or display) this string.

"randomly" is defined as all possibilities having an equal chance of being selected. This is a kind of simplification: in real languages as well as in conlangs, ​​there are very frequent (for example 'r' in English) and not very frequent sounds but this is just a code-golf.

Rules

This is code-golf so the lowest byte count wins.

Examples

Input:
C = ['p', 'b', 't', 'd', 'k', 'g', 'm', 'n', 'w']
V = ['a', 'o', 'u', 'i', 'e', 'ä']
S = 'CVCCV'

Output:
pakto
Input:
C = ['p', 'b', 't', 'd', 'k', 'g', 'v', 's', 'r']
V = ['a', 'o', 'u', 'i', 'e', 'ä', 'ᵫ']
S = 'CVVCCVCCV'

Output:
koebrᵫvtä

Victor VosMottor thanks Monica

Posted 2020-02-22T16:16:46.170

Reputation: 275

Can s be a string of 0s and 1s? And what about an integer with the bits indicating to use c or v? – RGS – 2020-02-22T16:28:00.800

@RGS Why do you need it? – Victor VosMottor thanks Monica – 2020-02-22T16:29:27.720

1To make it easier to pick consonants or vowels depending on what s has. – RGS – 2020-02-22T16:30:06.037

@RGS In task I've written: if C in s than consonant, else if V in s than vowels, ain't it? – Victor VosMottor thanks Monica – 2020-02-22T16:31:41.597

Exactly, I understand that. I just mean that if s was encoding that information in an easier way, it may create nicer solutions. – RGS – 2020-02-22T16:33:44.410

4

Please clarify what you mean by randomly. Also, do we really need to handle non-ASCII input?

– Luis Mendo – 2020-02-22T17:36:40.793

2Can each letter in C or V be used more than once? – Xcali – 2020-02-22T17:40:05.020

My guess is this was closed awaiting clarifications regarding Luis Mendo's questions above. – Jonathan Allan – 2020-02-24T01:01:39.547

@Luis Mendo I meant by randomly any pseudorandom library or algorithm with the same probability. Yes, you should handle non-ASCII input. – Victor VosMottor thanks Monica – 2020-02-24T12:32:21.193

1@VictorVosMottorthanksMonica You still haven't clarified what you mean by "randomly". Equally likely? Independent choices? Should each letter have non-zero probability? Please take a look at the meta post I linked to understand the problem – Luis Mendo – 2020-02-24T12:49:56.133

Answers

5

05AB1E, 4 bytes

Takes input as S, [V,C]

Çè€Ω

Try it online!

a'_'

Posted 2020-02-22T16:16:46.170

Reputation: 1 099

4

Jelly,  5  4 bytes

-1 thanks to Neil!

OịX€

A dyadic Link accepting a list of characters, S, on the left and a list of two lists of characters, [C, V], on the right which yields a list of characters.

Try it online!

If we could take S as a list of 1s and 0s we'd have the three byte solution ịX€.

How?

OịX€ - Link: S, [C,V]
O    - ordinals (of S)          i.e. 'C':67 'V':86
 ị   - index into [C,V] (vectorises)      C      V   [Jelly indexing is 1-indexed and modular]
   € - for each:
  X  -   random choice

Jonathan Allan

Posted 2020-02-22T16:16:46.170

Reputation: 67 804

I like both solutions! The 5 and the 3 byte ones +1 – RGS – 2020-02-22T16:54:15.227

What does Jelly do if an index is out of range? (Charcoal automatically reduces it modulo the range, so I don't need to extract the bit manually.) – Neil – 2020-02-22T17:42:40.470

@Neil you just saved a byte - thanks! I even noted in my code break-down that "Jelly indexing is 1-indexed and modular". – Jonathan Allan – 2020-02-22T17:47:56.747

3

Python 3, 92 68 61 bytes

Takes input as S, C, V:

lambda s,*w:[random.choice(w[a>"u"])for a in s]
import random

You can try it online! How it works:

The *w is used so that the lists of consonants and vowels are packed in a list w.

When we do w[a > "u"] we are essentially checking if a (a character of s) is "v" or not. If it is, then a > "u" returns True, which indexes as 1 into w. If a is "c", then a > "u" returns False, which indexes as 0.

We use those indices to retrieve the correct list of letters from w and then choose randomly from that list, picking the list of choices.

Thanks @Arnauld for saving one byte and to @Jonathan Allan for citing this meta, saving me 7 bytes.

RGS

Posted 2020-02-22T16:16:46.170

Reputation: 5 047

Really great!!! – Victor VosMottor thanks Monica – 2020-02-22T16:37:10.297

This is what I would've done in my C solution had it not been for that the lists of consonants and vowels are not of equal length. – S.S. Anne – 2020-02-22T17:57:04.977

I believe that you should be able to take s as a list of characters and return the same (see this meta) and as such can replace the "".join(...) with [...].

– Jonathan Allan – 2020-02-22T19:48:40.967

@JonathanAllan thanks for this reference! Shaved 7 bytes :) – RGS – 2020-02-22T20:51:09.597

3

APL+WIN, 35 34 bytes

One byte saved thanks to Adam

Prompts for consonants and vowels as continuous strings and the desired output as a comma separated string

c←⍞⋄v←⍞⋄C←',c[?⍴c]'⋄V←',v[?⍴v]'⋄⍎⎕

Try it online! Courtesy of Dyalog Classic

Graham

Posted 2020-02-22T16:16:46.170

Reputation: 3 184

If you liked this golf question, please vote to reopen it. – Victor VosMottor thanks Monica – 2020-02-23T14:01:48.677

If you don't like this golf challenge, please retain its closed state. – a'_' – 2020-02-23T14:23:39.260

This is the first time I have been lobbied from both sides of a question closure. Personally I had no problem understanding the question and as I got two up votes I assume at least two people agreed with my interpretation and my answer – Graham – 2020-02-23T15:04:50.710

By using instead of you can specify that input shouldn't have quotes, and then use instead of ⍎⎕ to save a byte: Try it online!

– Adám – 2020-02-25T13:48:12.220

@Adám Thanks for the suggestion but whilst it works in Dyalog Classic I cannot get it to work in APL+WIN. If I run the code as you suggest it simply outputs the concatenated code string which needs the second ⍎ to execute. – Graham – 2020-02-25T16:28:17.103

@Graham Even if the C,V,… is input into a ⎕: prompt without quotes? – Adám – 2020-02-25T16:29:37.687

@Adám It does work!!! Not sure why not before. I simply deleted the quotes around the inputs on my screen and successively hit enter on those lines when required. Finally typing each input when required I get the expected result. Thanks again for the suggestion. – Graham – 2020-02-25T17:00:29.530

@Graham Does v c←⍞⍞⋄C←',c[?⍴c]'⋄V←',v[?⍴v]'⋄⍎⎕ work in APL+WIN? – Adám – 2020-02-25T17:09:08.773

@Adám. No it throws an error. It does work if v c are enclosed in parentheses. In which case moving back to ⎕ allows a nested vector of v and c to be entered but we do not save any bytes. – Graham – 2020-02-25T18:08:07.287

@Graham Ah right, Dyalog is (unfortunately) lenient with that. Good for golfing, though. – Adám – 2020-02-25T18:09:10.357

2

Ruby, 45 40 bytes

->s,*l{s.bytes.map{|x|l[x%2].sample}*''}

Try it online!

G B

Posted 2020-02-22T16:16:46.170

Reputation: 11 099

I didn't think that ruby could outgolf python. Great! – Victor VosMottor thanks Monica – 2020-02-22T16:59:15.243

1Ruby code is usually shorter than the equivalent python code. – G B – 2020-02-23T07:14:23.217

2

Charcoal, 7 bytes

⭆η‽§θ℅ι

Try it online! Link is to verbose version of code. Takes the input in the form [V, C], S where each value can be either a string or an array of characters as desired. Explanation:

 η      `S`
⭆       Map over elements/characters
    θ   `[V, C]`
   §    Cyclically indexed by
     ℅  Ordinal of
      ι Current element/character
  ‽     Random element/character
        Implicitly print

Neil

Posted 2020-02-22T16:16:46.170

Reputation: 95 035

2

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

(C,V,s)=>s.Select(x=>(x<68?C:V).OrderBy(l=>Guid.NewGuid()).Last())

Try it online!

Embodiment of Ignorance

Posted 2020-02-22T16:16:46.170

Reputation: 7 014

2

Japt, 6 bytes

ËcgV ö

Takes input as S, [V,C]

Try it

Shaggy

Posted 2020-02-22T16:16:46.170

Reputation: 24 623

@a'_' Ok.6 more to go... – Victor VosMottor thanks Monica – 2020-02-23T14:28:06.297

@a'_' By the way, did you like this code-golf question? – Victor VosMottor thanks Monica – 2020-02-23T14:29:15.473

@VictorVosMottorthanksMonica I loved it. But it was blatant that I can't re-open it, because I don't have enough reputation to do so. – a'_' – 2020-02-23T14:30:37.493

Let us continue this discussion in chat.

– Victor VosMottor thanks Monica – 2020-02-23T15:14:10.330

2@VictorVosMottorthanksMonica, liking a challenge is not a valid reason to VTR it. Address the issues that led to it being closed and, once done so to the community's satisfaction, it will be reopened. – Shaggy – 2020-02-23T19:21:22.753

3@a'_', similarly, not liking a challenge is not grounds for closing it or leaving it closed. There have been many challenges here over the years I haven't personally liked, as there have been for everyone - if you don't like a challenge, just skip it and move on to the next one. – Shaggy – 2020-02-23T19:26:03.123

2

W f j, 4 bytes

Hmm, let's do a pure-ASCII port of that.

C[gr

Explanation

C    % Convert the string to its codepoints
 [   % Index into the other list
   r % For every indexed item:
  g  % "g"et a random item in this list

Flag:f % Flatten the output list
Flag:j % Join the flattened output list
```

a'_'

Posted 2020-02-22T16:16:46.170

Reputation: 1 099

1@KevinCruijssen I absolutely can't understand the challenge, so feel free to post your answer so that I can get a better understanding of this. (I guess I'd keep it deleted because I don't know how to fix it.) – a'_' – 2020-02-27T11:35:48.763

1

JavaScript (ES6),  65  64 bytes

(C,V,s)=>s.replace(/./g,x=>eval(x).sort(_=>Math.random()-.5)[0])

Try it online!

Or 55 bytes if we can use an array of characters as I/O.

Arnauld

Posted 2020-02-22T16:16:46.170

Reputation: 111 334

The eval trick is really nice! Sadly enough I don't think I can use it in my answer to save some bytes :( – RGS – 2020-02-22T16:49:05.090

55 seems fine unless OP has explicitly said not since I==O and if it quacks like a duck, it is a duck (i.e. strings are lists of characters)

– Jonathan Allan – 2020-02-22T19:46:23.410

@a'_' I think I'm privileged enough to hammer this question, which I think would be inappropriate either way. – Neil – 2020-02-24T10:19:49.593

1

PHP, 68 bytes

function($C,$V,$s){for(;$r=$s[$i++];)echo$$r[rand(0,count($$r)-1)];}

Try it online!

Guillermo Phillips

Posted 2020-02-22T16:16:46.170

Reputation: 561

1

C (gcc), 92 bytes

f(s,c,v,m,n)char*s,**c,**v;{for(srand(&s);*s;)printf("%s",*s++/86?v[rand()%n]:c[rand()%m]);}

Takes as input a string (s), an array of consonant strings (c), an array of vowel strings v, the length of c (m), and the length of v (n).

Could use a temporary variable for the result of rand but it wouldn't save me anything.

Try it online!

S.S. Anne

Posted 2020-02-22T16:16:46.170

Reputation: 1 161