| Bytes | Lang | Time | Link |
|---|---|---|---|
| 125 | sed r | 240612T210457Z | Jan Blum |
| 234 | Bash | 240610T103004Z | Themooni |
| 052 | 05AB1E | 240610T082935Z | Kevin Cr |
| 176 | Python | 240608T200802Z | Nicola S |
| 138 | JavaScript ES6 | 240608T142542Z | Arnauld |
| 082 | Charcoal | 240608T225309Z | Neil |
| 092 | Retina 0.8.2 | 240608T151253Z | Neil |
sed -r, 125 bytes
Expecting all-uppercase input
s/ (..? \w+|\S+)$/_&/
s/\W//g
:1
s/([AEIOU])([^AEIOU_])/\2\1/
t1
/^[^AEIOU_]{4}/s/(.)./\1/
s/_.*/X&X/
s/(...).*_(...).*/\2\1/
sed -r, 135 bytes
Variant that accepts input in either case
s/./\U&/g
s/ (..? \w+|\S+)$/_&/
s/\W//g
:1
s/([AEIOU])([^AEIOU_])/\2\1/
t1
/^[^AEIOU_]{4}/s/(.)./\1/
s/_.*/X&X/
s/(...).*_(...).*/\2\1/
Bash, 234 bytes
s=${@: -2:1}
l=${@: -1}
u=1
(($#>2&&`wc -m<<<$s`<4&&`grep -c [\'-]<<<$l`<1))&&l=$s$l&&u=2
f=${@:1:(($#-$u))}
v="[aeiou '-]"
p=[!aeiou]
c=${f//$v}
((`wc -m<<<$c`>4))&&c=${c:0:1}${c:2}
head -c3<<<${l//$v}${l//$p}x
head -c3<<<$c${f//$p}x
🏆: broke syntax highlighting
Call as a bash function or script, with the name as arguments in lowercase. You may need to escape 's as otherwise bash will try parsing a string.
ATO link has automatic lowercase conversion for your convenience.
thanks to @GammaFunction for his entry into a previous challenge that helped me separate consonnants and vowels.
explanation:
# implicit: bash automatically separates arguments by whitespace, so calling `script a b c` is equivalent to calling script(a, b, c) in other languages
s=${@: -2:1} # set s to the (s)econd to last argument
l=${@: -1} # set l to the (l)ast argument
u=1 # u counts the numer of arguments that make up the last name, 1 by default
$#>2 # there are more than 2 arguments
`wc -m<<<$s`<4 # the second to last argument has 2 characters or less (wc counts a trailing char, and < is shorter than <=, so we use 4 instead of 2)
`grep -c [\'-]<<<$l`<1 # the last argument has no `'` or `-`
(( && && )) # if the 3 last expressions are all true...
&&l=$s$l&&u=2 # then concatenate the last 2 arguments, making the last name, and set u to 2
f=${@:1:(($#-$u))} # set f to all arguments until u, making the (f)irst name
v="[aeiou '-]" #store a regular expression for later
p=[!aeiou] #store another regular expression
c=${f//$v} #set c to the (c)onsonnants in the first name, using the first regex.
((`wc -m<<<$c`>4)) #if there are more than 3 of them...
&&c=${c:0:1}${c:2} #set c to c[0]+c[2:], skipping the second consonnant
${l//$v}${l//$p}x #concat consonnants and vowels in the last name, and an additionnal x
head -c3<<< #trim the previous to 3 characters and output to stdout
head -c3<<<$c${f//$p}x #do the same to the first name, but using $c, which may have the second consonnant missing
05AB1E, 53 52 bytes
#R©¬a®g3@®1èg3‹**>®g‚£íðýlεáΣžMså}ÀDžNÃg4@N*.$Á'x«3£
Outputs as a lowercase pair of 3-char strings.
Try it online or verify all test cases.
Explanation:
Step 1: Split the input into first name and surname:
# # Split the (implicit) input-string on spaces
R # Reverse this list
© # Store it in variable `®` (without popping)
¬ # Push its first item (without popping the list)
a # Check if it's alphabetic (aka doesn't contain any "'-"-chars)
® # Push list `®` again
g # Pop and push the length of this list
3@ # Check if this list-length is >=3
® # Push list `®` yet again
1è # Pop and leave just its second item
g # Pop and push the length of this string
3‹ # Check if this string-length is <3
** # Combine all three checks
> # Increment this 0 or 1 to 1 or 2
®g # Push the length of list `®` again
‚ # Pair the two together
£ # Split the list into parts of those sizes
í # Reverse each inner list
ðý # Join each inner list with space delimiter
Step 2: Convert the surname and first name to the three letter Codice fiscale portions, and output the resulting pair:
l # Convert everything to lowercase
ε # Map over the pair with surname and first name:
á # Only leave the letters, removing " '-"-characters
Σ # Sort these letters by:
žM # Push the vowels(-y) constant string: "aeiou"
s # Swap so the current letter is at the top
å # Check if it's in this string
}À # After the sort: rotate the string once towards the left
D # Duplicate this string
žNÃ # Only keep all consonants(+y) of this copy
g # Pop and push the length of this consonants-string
4@ # Check if this consonants-length is >=4
N* # Multiply it by the 0-based map-index
.$ # Remove that many leading characters
Á # Rotate the string back once towards the right
'x« '# Append "x"
3£ # Pop and keep the first three characters
# (after which the result is output implicitly)
Python, 176 bytes
lambda F,K=lambda S,b="[\W":sub(b+"AEIOU]","",S):[(sub(f"(.){Q}.)",r"\1\2",K(P))+K(P,"[^")+"X")[:3]for P,Q in zip(split(" (.. ?\w+|\S+)$",F),[".(.","("])][::-1]
from re import*
Expects uppercase input. Outputs a list of two strings: surname, then name.
Based on my previous answer (below) but treats name and surname in a loop rather than explicitly.
Indebted to Arnauld for the name/surname regexp / (.. ?\w+|\S+)$/. The "4 letters, skip the second" regexp /(.).(..)/ is also used by Neil.
Previous (with explanation):
Python, 180 bytes
from re import*
K=lambda S,b=0:sub("[[\^W"[b::2]+"AEIOU]","",S)+"X"*b
def f(F):
n,s,_=split(" (.. ?\w+|\S+)$",F)
return(K(s)+K(s,1))[:3]+(sub("(.).(..)",r"\1\2",K(n))+K(n,1))[:3]
Expects uppercase input.
Explanation
from re import* # We will be using regexps.
K=lambda S,b=0: # Utility function. Takes a string and a 0/1 flag.
sub("[[\^W"[b::2]+"AEIOU]","",S) # If b=0, deletes vowels and symbols ([\WAEIOU]).
# If b=1, deletes everything except vowels ([^AIEOU]).
+"X"*b # If b=1, it also adds a "X".
def f(F):
n,s,_=split(" (.. ?\w+|\S+)$",F) # Arnauld's regexp splits name (n) and surname (s).
return(K(s)+K(s,1) # Call K() on s, first for consonants (b=0), then for
# vowels and trailing "X" (b=1), and...
)[:3] # keep 3 chars.
+( # Same for n, but, ...
sub("(.).(..)",r"\1\2",K(n)) # if K(n,0) contains any seq of 4 chars ("(X)Y(ZW)"),
# keep only the two groups in parentheses: "XZW".
+K(n,1))[:3]
PS
Answering my own question (which is allowed, although waiting some time is advised). I only waited 8 hours because I didn't really get a head start (thought about this problem this morning), and I'm less proficient than other Python golfers so I don't believe this is going to be a winning Python entry.
In particular, I liked the regexp-based answers that have been posted so I wanted to try my own.
JavaScript (ES6), 138 bytes
Expects the input in lowercase and returns a string in lowercase as well.
s=>(g=r=>(s.split(/ (.. ?\w+|\S+)$/)[+!r].replace(/[aeiou\W]/g,c=>(c>{}?v+=c:0,""),v="").replace(r,"")+v+"x").slice(0,3))()+g(/\B.(?=..)/)
Commented
s => ( // s = input string
g = r => ( // g is a helper function taking a regex r
s.split( // split the original string ...
/ (.. ?\w+|\S+)$/ // ... using a regex that matches the surname
)[+!r] // keep the name if r is defined,
// or the surname otherwise
.replace( // replace:
/[aeiou\W]/g, // match all vowels and non-letter characters
c => ( // for each matched character c:
c > {} ? // if c is a letter (i.e. a vowel):
v += c // append it to v
: // else:
0, // do nothing
"" // always remove the original character
), //
v = "" // start with v = "" (string of vowels)
) // end of replace() -> only consonants remain
.replace(r, "") + // apply the regex r to conditionally remove
// the second consonant (for the name only)
v + "x" // append the vowels and a trailing "x"
).slice(0, 3) // keep the first 3 characters
)() + // 1st call to g for the surname with no regex
g( // 2nd call to g for the name with a regex that
/\B.(?=..)/ // matches the 2nd character if the 4th one is
) // defined
Charcoal, 82 bytes
≔AEIOUθ≔⪪S η≔⟦⪫⮌E⊕∧⬤§η±¹№αι›³L§η±²⊟ηω⪫ηω⟧ηUMη⭆²Φι∧№αν⁼λ№θν⭆η…⁺Φι∨¬κ∨⊖μ№θ§⁺§η¹AA³X³
Try it online! Link is to verbose version of code. Takes input in upper case (could take in mixed case at a cost of a byte). Explanation:
≔AEIOUθ
Get the vowels in a variable as this saves a byte.
≔⪪S η
Input the name and split it on spaces.
≔⟦⪫⮌E⊕∧⬤§η±¹№αι›³L§η±²⊟ηω⪫ηω⟧η
Extract the surname and given name.
UMη⭆²Φι∧№αν⁼λ№θν
For each name, sort the consonants to the start and the vowels to the end and ignore other characters.
⭆η…⁺Φι∨¬κ∨⊖μ№θ§⁺§η¹AA³X³
Remove the second consonant of four in the given name, then take the first three letters of each name, filling with X if necessary.
Retina 0.8.2, 94 92 bytes
(.+?) (..? \w+|\S+)$
$2¶$1
%`\W
%O$`([AEIOU])|.
$.1
(¶.).(.[^AEIOU])
$1$2
%`$
X
%M!`^...
¶
Try it online! Takes input in upper case but link is to test suite that uppercases input. Explanation:
(.+?) (..? \w+|\S+)$
$2¶$1
Extract the surname and given name. (Note: this assumes that there won't be two spaces in a row.)
%`\W
Remove all non-letters, but on each name separately, so that the newline doesn't get removed.
%O$`([AEIOU])|.
$.1
Sort the vowels to the end on each name separately.
(¶.).(.[^AEIOU])
$1$2
Remove the second consonant of the given name if there are at least four.
%`$
X
%M!`^...
For each name, take the first three letters, filling in with an X if there are only two.
¶
Join the codes of the surname and given name together.
Edit: Saved 2 bytes thanks to @Arnauld.