15
\$\begingroup\$

Disclaimer: This isn't my challenge but ThisGuy said I was OK to post.


Occasionally I want to make a word into it's opposite, like happiness goes to unhappiness. Unfortunately when this happens, my brain will sometimes go blank. Then one day, after yet another this happening, I thought to my self "This is what programs are for!"

As the English language has many exceptions, I have created a list which contains the prefix for the starting letter

q or h -> dis- (honest -> dishonest)
l -> il- (legal -> illegal)
m or p -> im- (mature -> immature)
r -> ir- (responsible -> irresponsible)
everything else -> un- (worthy -> unworthy)

Task

Given an input as a string, make the string into its negative and output the result. You can assume that all the inputs given will fit the above rules. Submissions may be programs or functions, not snippets.

Input

A single string, taken either as a parameter or from STDIN

Output

The negated form of that string, conforming to the above rules

How to Win

This is a so shortest code wins

Magic Octopus Urn
20.9k6 gold badges66 silver badges140 bronze badges
asked Apr 5, 2017 at 19:49
\$\endgroup\$
9
  • 4
    \$\begingroup\$ Can we assume we'll never get a word that starts with a q without a u? \$\endgroup\$ Commented Apr 5, 2017 at 20:06
  • 3
    \$\begingroup\$ Off the top of my head, qadi, qat, the aforementioned qi, qirsh, and qwerty. (I play a lot of Scrabble) \$\endgroup\$ Commented Apr 5, 2017 at 20:23
  • 4
    \$\begingroup\$ @wsbltc Well, there's a fair few, but they're pretty much all borrowed words from other languages so questionable whether they really count as English. So can we assume that a q is always followed by a u in the string or not? \$\endgroup\$ Commented Apr 5, 2017 at 20:24
  • 3
    \$\begingroup\$ Yes you can assume it always has a u \$\endgroup\$ Commented Apr 5, 2017 at 20:48
  • 12
    \$\begingroup\$ This challenge could make a pedant quite dishappy... \$\endgroup\$ Commented Apr 6, 2017 at 10:08

20 Answers 20

10
\$\begingroup\$

Python, 55 bytes

lambda n:'ddiiiiuiimmlrnss'[5-'rlmphq'.find(n[0])::7]+n

Try it online!


We need to handle 7 different starting letters:
g -> dis, h -> dis, p -> im, m -> im, l -> il, r -> ir and everything else -> un

We can store all these negations in a single string and extract the right one through slicing:

 d i s
 d i s
 i m
 i m
 i l
 i r
 u n
'ddiiiiuiimmlrnss'[i::7]

Now we need to calculate the start index i. 'rlmphq'.find returns 0 for 'r', 5 for q and -1 for everything not contained in the string. To get the needed value from 0 to 6 we still need to subtract the return value from 5, resulting in this code:

'ddiiiiuiimmlrnss'[5-'rlmphq'.find(n[0])::7]
answered Apr 5, 2017 at 20:53
\$\endgroup\$
3
  • \$\begingroup\$ That's really cute! \$\endgroup\$ Commented Apr 6, 2017 at 10:59
  • \$\begingroup\$ Can someone explain how the hell is this works? I understand what's going on with the slice notation, but what are the magic strings ddiiiiuiimmlrnss and rlmphq and the number 5 for, why is the slice skip 7? \$\endgroup\$ Commented Apr 6, 2017 at 19:51
  • \$\begingroup\$ @Keatinge added an explanation. I hope it helps you \$\endgroup\$ Commented Apr 6, 2017 at 20:52
6
\$\begingroup\$

GNU sed, 50 bytes

Includes +1 for -r

s/^q|^h/dis&/
s/^l|^r|^m/i&&/
s/^p/imp/
t
s/^/un/

Nothing fancy. Uses & in the replacement to combine a few substitutions, and t to skip the last one if one of the first substitutions happens.

Try it online!

answered Apr 5, 2017 at 21:29
\$\endgroup\$
5
\$\begingroup\$

Jelly, 30 bytes

1ị"qmlrrhp"iị"3bμWI=ṡ÷ʠ$»œs5¤;

Try it online!

How?

1ị"qmlrrhp"iị"3bμWI=ṡ÷ʠ$»œs5¤; - Main link: string
1ị - 1 index into the string (first character of the string)
 i - 1-based index of 1st occurrence of that in (else zero):
 "qmlrrhp" - char list "qmlrrhp"
 ị - index into (1-based and modulo):
 ¤ - nilad followed by link(s) as a nilad:
 "3bμWI=ṡ÷ʠ$» - compressed string "dis"+"imili"+"run"="disimilirun"
 œs5 - split "equally" into 5: ["dis","im","il","ir","un"]
 ; - concatenate with the string
 

Note that the repeated r in "qmlrrhp" is in the 5th index, which, if referenced, would result in prepending un, so it could equally well be anything other than h or p.

answered Apr 5, 2017 at 21:49
\$\endgroup\$
4
\$\begingroup\$

TI-Basic, 104 bytes

Prompt Str0
sub(Str0,1,1→Str2
Str0
If Str2="Q" or Str2="H
"DIS"+Ans
If Str2="L
"IL"+Ans
If Str2="M" or Str2="P
"IM"+Ans
If Str2="R
"IR"+Ans
If Ans=Str0
"UN"+Ans
Ans

Requires all capital letters.

Explanation:

Prompt Str0 # 4 bytes, input user string to Str0
sub(Str0,1,1→Str2 # 12 bytes, store first character in Str2
Str0 # 3 bytes, store Str0 in Ans
If Str2="Q" or Str2="H # 14 bytes, if the first letter was Q or H
"DIS"+Ans # 8 bytes, store DIS+Ans in Ans
If Str2="L # 7 bytes, If the first letter was L
"IL"+Ans # 7 bytes, store IL+Ans in Ans
If Str2="Q" or Str2="H # 14 bytes, if the first letter was Q or H
"IM"+Ans # 7 bytes, store DIS+Ans in Ans
If Str2="R # 7 bytes, if the first letter was R
"IR"+Ans # 7 bytes, store IR+Ans in Ans
If Ans=Str0 # 6 bytes, if Ans has not been changed (first letter was none of the above)
"UN"+Ans # 7 bytes, store UN+Ans in Ans
Ans # 1 byte, implicitly return Ans
answered Apr 5, 2017 at 21:25
\$\endgroup\$
1
  • \$\begingroup\$ 81 bytes \$\endgroup\$ Commented Jun 6, 2021 at 22:08
4
\$\begingroup\$

///, (削除) 59 (削除ここまで) 56 bytes

/^/\/\/#//#qu/disqu^h/dish^l/ill^m/imm^p/ipp^r/irr^/un/#

Try it online!

Input goes after the very last #.

How it works:

I made an optimization that reduced the size to 56 bytes, but since that complicates things I will explain the original version, then explain the golf.

/#qu/disqu//#h/dish//#l/ill//#m/imm//#p/ipp//#r/irr//#/un/# |everything after the ` |` is not code.
/#qu/disqu/ |replace `qu` with `disqu`
 /#h/dish/ |replace `h` with `dish`.
 /#l/ill/ |replace `l` with `ill`.
 /#m/imm/ |replace `m` with `imm`.
 /#p/ipp/ |replace `p` with `ipp`.
 /#r/irr/ |replace `r` with `irr`.
 /#/un/ |replace everything else with `un`.
 # |safety control

Intuition: The challenge is simple enough, just add the negative depending on the beginning of the word. However, in ///, you cannot just concatenate if [...], you can only replace something following a specific pattern. So in this program, the positive word beginnings are replaced with the negative word beginnings. The # was added to make sure that once a new beginning was added, no more new beginnings would be added. The # also made it possible to do 'everything else: un'.

The golf incorporates a new substitution at he beginning: /^/\/\/#/. This replaces all ^ with //#, which was a common pattern in the original version.

answered Apr 5, 2017 at 20:02
\$\endgroup\$
3
\$\begingroup\$

Batch, 114 bytes

@set/pw=
@set p=un
@for %%p in (dis.q dis.h il.l im.m im.p ir.r)do @if .%w:~,1%==%%~xp set p=%%~np
@echo %p%%w%

Checks the first character of the word against the list of custom prefixes and if so changes the prefix from the default of un. Special-casing qu is possible at a cost of 21 bytes.

answered Apr 5, 2017 at 20:42
\$\endgroup\$
3
\$\begingroup\$

Javascript, (削除) 72 (削除ここまで) (削除) 71 (削除ここまで) (削除) 66 (削除ここまで) (削除) 61 (削除ここまで) (削除) 60 (削除ここまで) 59 bytes

(削除) w=>('dis....il.im...im.dis.ir'.split('.')[w.charCodeAt(0)-104]||'un')+w (削除ここまで)

(削除) w=>'un.dis.dis.il.im.im.ir'.split('.')['qhlmpr'.indexOf(w[0])+1]+w (削除ここまで)

(削除) Yeah, it's still longer than an existing solution. :) (削除ここまで)

w=>['un','dis','im','il','ir']['qmlrhp'.search(w[0])%4+1]+w

In case this needs any explanation, I'm taking advantage of the q/h and m/p pairs by combining their index in the search string with a mod 4, then using that as the lookup into the prefix array.

Okx
16.5k5 gold badges45 silver badges114 bronze badges
answered Apr 6, 2017 at 7:27
\$\endgroup\$
2
  • \$\begingroup\$ Great answer. Save 1 byte using search instead of indexOf. And some more, I think, using & instead of % \$\endgroup\$ Commented Apr 6, 2017 at 10:53
  • \$\begingroup\$ Thank you! I didn't know about search. Can't see how to make the & trick work - would be perfect if my array was only 4 elements. \$\endgroup\$ Commented Apr 6, 2017 at 11:07
3
\$\begingroup\$

JavaScript ((削除) 71 (削除ここまで) (削除) 64 (削除ここまで) 61 bytes)

w=>({q:a='dis',h:a,l:'il',m:b='im',p:b,r:'ir'}[w[0]]||'un')+w

Edits:

  • Saved 7 bytes thanks to @ErtySeidohl (charAt(0) -> [0])
  • Saved 3 bytes thanks to @edc65 (assigning shared prefixes to variables)

var f = w=>({q:a='dis',h:a,l:'il',m:b='im',p:b,r:'ir'}[w[0]]||'un')+w;
function onChange() {
 var word = event.target.value;
 var output = f(word);
 document.getElementById('output').innerHTML = output;
}
Input Word: <input type='text' oninput='onChange()'/><br/>
Output Word: <span id="output">

answered Apr 5, 2017 at 23:22
\$\endgroup\$
5
  • 1
    \$\begingroup\$ If you don't care about backward compatibility with IE7, couldn't you use w[0] instead of w.charAt(0)? \$\endgroup\$ Commented Apr 6, 2017 at 2:21
  • \$\begingroup\$ @ErtySeidohl Thanks! Just learned something new ;-) \$\endgroup\$ Commented Apr 6, 2017 at 4:41
  • \$\begingroup\$ I'm new here, but is it legitimate to provide an answer starting with just w=>...? The actual function definition would include let f=w=>... ? (Probably covered in an FAQ somewhere...) \$\endgroup\$ Commented Apr 6, 2017 at 7:10
  • \$\begingroup\$ @SteveBennett yes it's legitimate. Naming the function is not relevant \$\endgroup\$ Commented Apr 6, 2017 at 10:32
  • 1
    \$\begingroup\$ w=>({q:a='dis',h:a,l:'il',m:b='im',p:b,r:'ir'}[w[0]]||'un')+w 3 bytes less \$\endgroup\$ Commented Apr 6, 2017 at 10:52
2
\$\begingroup\$

Haskell, 71 bytes

f l=maybe"un"id(lookup(l!!0)$zip"qhlmpr"$words"dis dis il im im ir")++l

Usage example: f "legal"-> "illegal". Try it online!

Build a lookup table of prefix/replacement pairs for looking up the first char of the input string with a default value of "un" if not found.

answered Apr 5, 2017 at 21:01
\$\endgroup\$
2
\$\begingroup\$

Mathematica, 107 bytes

StringReplace[StartOfString~~x:#:>#2<>x&@@@{{"q"|"h","dis"},{"l","il"},{"m"|"p","im"},{"r","ir"},{_,"un"}}]

Explanation:

StartOfString~~x:#:>#2<>x& is a pure function where the first argument is a string pattern to match at the beginning of the string and the second argument is a string to prepend to the match. It returns a delayed rule suitable for use within StringReplace. This is then applied to each of the pairs {{"q"|"h","dis"},{"l","il"},{"m"|"p","im"},{"r","ir"},{_,"un"}} resulting in the list of rules

{
 StartOfString~~x:"q"|"h":>"dis"<>x,
 StartOfString~~x:"l":>"il"<>x,
 StartOfString~~x:"m"|"p":>"im"<>x,
 StartOfString~~x:"r":>"ir"<>x,
 StartOfString~~x_:>"un"<>x
}

Finally this list is passed into StringReplace which gives an operator on strings.

answered Apr 5, 2017 at 21:13
\$\endgroup\$
1
  • 2
    \$\begingroup\$ Does Mathmatica have a builtin for everything? \$\endgroup\$ Commented Apr 5, 2017 at 21:14
2
\$\begingroup\$

Retina, 54 bytes

^[^hqlmpr]
un$+
^[hq]
dis$+
^l
il$+
^[mp]
im$+
^r
ir$+

Explanation:

 {implicit replace stage}
^[^hqlmpr] Append un to words starting with none of: hqlmpr
un$+ 
^[hq] Append dis to words starting with h or q
dis$+ 
 ^l Append il to words starting with l
il$+ 
^[mp] Append il to words starting with m or p
im$+ 
^r Append ir to words starting with r
ir$+

First time I've used Retina. It's a pretty neat language.

Try it online!

answered Apr 6, 2017 at 8:04
\$\endgroup\$
4
  • \$\begingroup\$ Very nice first try at a language! +1 \$\endgroup\$ Commented Apr 6, 2017 at 8:22
  • \$\begingroup\$ And with that you have 2500 rep! Congratulations! \$\endgroup\$ Commented Apr 6, 2017 at 8:23
  • \$\begingroup\$ And your user index is 26600! \$\endgroup\$ Commented Apr 6, 2017 at 8:23
  • \$\begingroup\$ So much perfect base-10 ! \$\endgroup\$ Commented Apr 6, 2017 at 8:24
1
\$\begingroup\$

C, (削除) 109 (削除ここまで) 107 bytes

f(char*s){printf("%s%s",*s-109&&*s-112?*s-108?*s-114?*s-104&&*s-113|s[1]-117?"un":"dis":"ir":"il":"im",s);}

Try it online!

answered Apr 5, 2017 at 20:06
\$\endgroup\$
1
\$\begingroup\$

PHP, 101 Bytes

echo preg_match("#^(qu|[hlmpr])#",$argn,$t)?[qu=>dis,h=>dis,l=>il,m=>im,p=>im,r=>ir][$t[1]]:un,$argn;

Online Version

answered Apr 5, 2017 at 21:26
\$\endgroup\$
1
\$\begingroup\$

Excel 78 bytes

=TRIM(MID(" disdisil im im ir un",IFERROR(FIND(LEFT(A1),"qhlmpr"),7)*3,3))&A1

I found some close contenders using different methods that scored 81 bytes:

=IFERROR(CHOOSE(FIND(LEFT(A1),"qhlmpr"),"dis","dis","il","im","im","ir"),"un")&A1

And 84 bytes:

=IFERROR(TRIM(MID("im disi"&LEFT(A1),MOD(FIND(LEFT(F1),"qlmhrp"),3)*3+1,3)),"un")&A1
answered Apr 6, 2017 at 17:13
\$\endgroup\$
0
\$\begingroup\$

REXX, 78 bytes

arg a
s.=un
s.q=dis
s.h=s.q
s.l=il
s.m=im
s.p=im
s.r=ir
p=left(a,1)
say s.p||a

Saves a few bytes by replying in UPPERCASE, e.g. potent -> IMPOTENT.

answered Apr 6, 2017 at 8:19
\$\endgroup\$
0
\$\begingroup\$

Perl, 49 + 1 (-p flag) = 50 bytes

s|^[hq]|dis$&|||s|^[lmr]|i$&$&|||s|p|imp|||s||un|

Using:

perl -pe 's|^[hq]|dis$&|||s|^[lmr]|i$&$&|||s|p|imp|||s||un|' <<< responsible

Try it online.

answered Apr 6, 2017 at 8:27
\$\endgroup\$
0
\$\begingroup\$

Clojure, 65 bytes

#(str(get{\q"dis"\h"dis"\l"il"\m"im"\p"im"\r"ir"}(first %)"un")%)

Well this is boring... but I couldn't make it any shorter. At least there is very little whitespace.

answered Apr 6, 2017 at 8:48
\$\endgroup\$
0
\$\begingroup\$

OCaml, 85

(fun s->(match s.[0]with|'q'|'h'->"dis"|'l'->"il"|'m'|'p'->"im"|'r'->"ir"|_->"un")^s)

Anonymous function, uses pattern matching on its first char.

answered Apr 6, 2017 at 10:45
\$\endgroup\$
0
\$\begingroup\$

Vyxal, 38 bytes

«÷c4w«?hḟ:u=[`un`|4%«⟑Ẇf:«2ẇ`Ġ⟨`p$i]?+

Try it Online!

Messy.

answered Jun 6, 2021 at 5:27
\$\endgroup\$
0
\$\begingroup\$

PowerShell, (削除) 66 (削除ここまで) 62 bytes

%4+1 inspired by @Steve Bennett

param($s)(echo un dis im il ir)[('qmlrhp'|% I*f $s[0])%4+1]+$s

Try it online!

answered Jun 6, 2021 at 8:23
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.