30
\$\begingroup\$

Challenge description

In this challenge, we only consider love and hate as feelings. If we want to utter a feeling expression of order N, we alternate between these two (starting with hate):

order | expression

1       I hate it.
2       I hate that I love it.
3       I hate that I love that I hate it.
4       I hate that I love that I hate that I love it.

The pattern follows for every positive integer N. Given N, output the correspoinding feeling expression of order N.

Notes

  • Full stop (.) at the end of the expression is mandatory,
  • Trailing and leading whitespaces (including newlines) are permitted,
  • Output for a non-positive or non-integer N is undefined,
  • This is a challenge, so make your code as short as possible!
\$\endgroup\$
  • \$\begingroup\$ Related. \$\endgroup\$ – Leaky Nun Aug 31 '16 at 10:16
  • 1
    \$\begingroup\$ Quite confused. So is order the input, and expression the output? \$\endgroup\$ – Whothehellisthat Aug 31 '16 at 13:43
  • 2
    \$\begingroup\$ @Whothehellisthat Yes, exactly. (Welcome to PPCG! :)) \$\endgroup\$ – Martin Ender Aug 31 '16 at 13:46
  • \$\begingroup\$ @Whothehellisthat: Yes. You may take input through stdin, though it's often shorter to define a method (function), as you can see in the submissions below. \$\endgroup\$ – shooqie Aug 31 '16 at 14:23
  • 1
    \$\begingroup\$ I hate that I love this question and its answers! \$\endgroup\$ – Arkiliknam Sep 2 '16 at 11:35

29 Answers 29

21
\$\begingroup\$

Python, 54 bytes

lambda n:("I hate that I love that "*n)[:12*n-5]+"it."
\$\endgroup\$
  • \$\begingroup\$ Ported to Haskell: f n=take(12*n-5)(cycle"I hate that I love that ")++"it." (56 bytes) \$\endgroup\$ – xnor Sep 1 '16 at 2:06
15
\$\begingroup\$

CJam, 36 bytes

ri{"hatlov"3/='IS@"e that "}/2<"it."

Try it online!

Explanation

ri            e# Read input and convert to integer N.
{             e# For each i from 0 to N-1...
  "hatlov"3/  e#   Push ["hat" "lov"].
  =           e#   Use i as a cyclic index into this array to alternate between
              e#   "hat" and "lov".
  'IS         e#   Push character 'I' and a space.
  @           e#   Pull "hat" or "lov" on top of it.
  "e that "   e#   Push "e that "
}/
2<            e#   Truncate the last "e that " to just "e ".
"it."         e#   Push "it."
\$\endgroup\$
7
\$\begingroup\$

C, 83 76 75 74 bytes

Thanks to @Leaky Nun for saving 11 bytes and adding 4 bytes!
Thanks to @YSC for saving a byte!

i;f(n){for(i=0;n--;)printf("I %se %s",i++%2?"lov":"hat",n?"that ":"it.");}

Try it on Ideone

\$\endgroup\$
  • 1
    \$\begingroup\$ i=0;while(n--) -> for(i=0;n--;) saves 1 char. \$\endgroup\$ – YSC Aug 31 '16 at 11:39
6
\$\begingroup\$

Javascript (ES6), 75 73 70 bytes

n=>[...Array(n)].map((_,i)=>i&1?'I love':'I hate').join` that `+' it.'

Saved 2 bytes thanks to Neil
Saved 3 bytes thanks to Whothehellisthat

Test

let f =
n=>[...Array(n)].map((_,i)=>i&1?'I love':'I hate').join` that `+' it.'

console.log(f(1))
console.log(f(2))
console.log(f(3))
console.log(f(4))

\$\endgroup\$
  • \$\begingroup\$ Save 3 bytes: ['I hate','I love'][i&1] -> i&1?'I love':'I hate' \$\endgroup\$ – Whothehellisthat Aug 31 '16 at 14:19
  • \$\begingroup\$ @Whothehellisthat - Thanks! I missed that one. \$\endgroup\$ – Arnauld Aug 31 '16 at 14:26
5
\$\begingroup\$

Java 8, 91 bytes

i->{for(int j=0;j++<i;)System.out.printf("I %se %s",j%2>0?"hat":"lov",j<i?"that ":"it.");};

Ungolfed Test Program

public static void main(String[] args) {
    Consumer<Integer> c = i -> {
        for (int j = 0; j++ < i;) {
            System.out.printf("I %se %s", j % 2 > 0 ? "hat" : "lov", j < i ? "that " : "it.");
        }
    };

    c.accept(1);
    c.accept(2);
    c.accept(3);
}
\$\endgroup\$
  • \$\begingroup\$ Why not remove the whitespace? c=i->for(...) \$\endgroup\$ – shooqie Aug 31 '16 at 11:24
  • \$\begingroup\$ I simply forgot. \$\endgroup\$ – Shaun Wild Aug 31 '16 at 12:47
  • \$\begingroup\$ Nice, you've beat me to it. +1 And probably shorter than my answer would be. PS: I would indicate this as 'Java 8' instead of just 'Java'. Not mandatory however, just personal preference from me since I usually write my answers in Java 7 (and since Java 9 is incoming). \$\endgroup\$ – Kevin Cruijssen Aug 31 '16 at 12:55
  • \$\begingroup\$ @KevinCruijssen You tell me this everytime ;) fine \$\endgroup\$ – Shaun Wild Aug 31 '16 at 13:13
  • \$\begingroup\$ @SeanBean Well, usually I already have my Java 7 answer, and you post a shorter answer, which can then most of the time be golfed even more. ;P (This time I can't find anything to make it shorter, though. But perhaps someone else is able to do so.) \$\endgroup\$ – Kevin Cruijssen Aug 31 '16 at 13:37
5
\$\begingroup\$

Mathematica, 63 bytes

"I love"["I hate"][[#~Mod~2]]&~Array~#~Riffle~" that "<>" it."&
\$\endgroup\$
  • 1
    \$\begingroup\$ I'm loving the head extraction there, really clever. \$\endgroup\$ – A Simmons Aug 31 '16 at 13:46
  • \$\begingroup\$ @ASimmons It's actually quite an old trick (which I didn't even come up with myself), but I definitely don't get to use it often enough. ;) \$\endgroup\$ – Martin Ender Aug 31 '16 at 13:51
5
\$\begingroup\$

Jelly, 25 bytes

“ṅɠT5“£ẏkg⁷»ṁj“¥ıQ»ṙ1“it.

Try it online!

Explanation

                             Input: n, a number.
“ṅɠT5“£ẏkg⁷»                 Compressed string array [' I hate', ' I love']
            ṁ                Cycle for n repetitions.
             j“¥ıQ»          Join by compressed string ' that'.
                   ṙ1        Rotate left once: move the initial space to the end.
                     “it.    Implicitly print the result, then print 'it.'
\$\endgroup\$
  • \$\begingroup\$ I need an explanation for this. \$\endgroup\$ – Steven H. Aug 31 '16 at 22:12
4
\$\begingroup\$

05AB1E, 34 32 27 bytes

Saved 5 bytes thanks to Adnan.

“I«¢€Š I„΀Š “×¹12*5-£…it.«

Explanation

“I«¢€Š I„΀Š “               # "I hate that I love that "
              ×              # repeat input nr of times
               ¹12*5-£       # take the first input*12-5 chars of string above
                      …it.«  # append "it."
                             # implicitly display

Try it online!

\$\endgroup\$
4
\$\begingroup\$

R, 79 bytes

n=scan();for(i in n:1)cat(if((i+n)%%2)"I love"else"I hate",if(i>1)"that "else"it.")

Luckily in R, the default separator for cat is a space.

(Edited from original 73 byte version which didn't quite solve the problem.)

\$\endgroup\$
  • \$\begingroup\$ Neat use of the for loop and %%. +1 \$\endgroup\$ – Billywob Aug 31 '16 at 14:11
2
\$\begingroup\$

Retina, 42 38 bytes

Thanks to Leaky Nun for helping me golf it!

11
1I love n
1
I hate n
n$
it.
n
that 

Input is taken in unary.

Try it online!

Explanation

11
1I love n

Replace every pair of 1s with 1I love n.

1
I hate n

Replace the remaining 1s with I hate n.

n$
it.
n
that 

Replace the n at the end of the line with it. and every other n with that .

\$\endgroup\$
  • \$\begingroup\$ You can save four more by dropping l: retina.tryitonline.net/… \$\endgroup\$ – Martin Ender Aug 31 '16 at 13:21
  • \$\begingroup\$ @MartinEnder: I think I ninja'd you to that edit :P \$\endgroup\$ – Business Cat Aug 31 '16 at 13:38
  • 1
    \$\begingroup\$ Timestamps say you were 9 seconds late. :P \$\endgroup\$ – Martin Ender Aug 31 '16 at 13:38
1
\$\begingroup\$

Javascript (ES5), 99 94 bytes

function(c){for(d="",b=0;b<c;++b)d+=(b%2?"I love ":"I hate ")+(b==c-1?"it.":"that ");return d}

Saved 5 bytes thanks to Leaky Nun.

OLD 99 byte solution:

function(c){for(d="",b=0;b<c;++b)d+=(0==b%2?"I hate":"I love")+" "+(b==c-1?"it.":"that ");return d}

Another 98 byte solution:

function(d){for(c=[],b=0;b<d;++b)c.push(["love","hate"][b%2]);return"I "+c.join(" that I ")+" it"}

My code before minification:

function a(n){
  var hate="I hate",love="I love",it="it ",that="that ",out="";
  for(var i=0;i<n;++i){out+=(i%2==0?hate:love)+" "+(i==n-1?it+".":that)}return out;
}
\$\endgroup\$
  • 1
    \$\begingroup\$ function(c){for(d="",b=0;b<c;++b)d+=(b%2?"I love ":"I hate ")+(b==c-1?"it.":"that ");return d} \$\endgroup\$ – Leaky Nun Aug 31 '16 at 10:28
1
\$\begingroup\$

Haskell, 70 bytes

g 1="I hate";g n=g(n-1)++" that "++cycle["I love",g 1]!!n
(++" it.").g
\$\endgroup\$
1
\$\begingroup\$

PowerShell v2+, 64 bytes

((1..$args[0]|%{('I love','I hate')[$_%2]})-join' that ')+' it.'

Rather straightforward. Loops from 1 up to the input $args[0], each iteration placing either 'I love' or 'I hate' on the pipeline, based on a pseudo-ternary for modulo-2 (i.e., it alternates back and forth, starting with 'I hate'). Those strings are encapsulated in parens and -joined with ' that ' to smush them together, then string concatenation ' it.' at the end.

Test Cases

PS C:\Tools\Scripts\golfing> 1..5|%{.\hate-love-conundrum.ps1 $_}
I hate it.
I hate that I love it.
I hate that I love that I hate it.
I hate that I love that I hate that I love it.
I hate that I love that I hate that I love that I hate it.
\$\endgroup\$
1
\$\begingroup\$

php, 64 62 bytes

<?=str_pad("",$argv[1]*12-5,"I hate that I love that ")."it.";

Unfortunately I couldn't work out a way to avoid repeating the " that I ", or at least no way to do it in less than 7 bytes.

edit: saved 2 bytes thanks to @Jörg Hülsermann

\$\endgroup\$
1
\$\begingroup\$

Perl, 62 54 50 bytes

$_="I xe tx "x$_;s/tx $/it./;s/x/++$.%4?hat:lov/ge

(credit to @Ton Hospel)

Demo: http://ideone.com/zrM27p

Previous solutions:

$_="I xe that "x$_;s/x/$@++&1?lov:hat/ge;s/\w+.$/it./

(credit to @Dada)

Run with perl -pE '$_="I xe that "x$_;s/x/$@++&1?lov:hat/ge;s/\w+.$/it./'

First solution (only this was mine)

for$x(1..<>){$_.=' I '.($x%2?hat:lov).'e that'}s/\w+$/it./;say

In parts:

for $x (1..<>) {
   $_ .= ' I '.($x % 2 ? hat : lov).'e that'
}
s/\w+$/it./;
say

Demo: http://ideone.com/mosnVz

\$\endgroup\$
  • \$\begingroup\$ Hi and welcome to PPCG. Nice answer. Here is a shorter solution though (54 bytes) : perl -pE '$_="I xe that "x$_;s/x/$@++&1?lov:hat/ge;s/\w+.$/it./'. \$\endgroup\$ – Dada Sep 1 '16 at 0:07
  • \$\begingroup\$ What does this part mean $@++&1? For @+ perldoc says "holds the offsets of the ends of the last successful submatches in the currently active dynamic scope" which doesn't make much sense for me. As I understand, you use this array in scalar context ($@+ - are you dereferencing it?) to get the number of elements and then add (+) the matched string (&1). No no no I knew I shouldn't have posted to PPCG it's too obfuscated :D \$\endgroup\$ – Al.G. Sep 1 '16 at 10:16
  • \$\begingroup\$ $@ is just a scalar (I could have used $x or any other scalar), ++ is the increment operator, and &1 is roughly the same as %2. So it's basically the same as $x++%2. \$\endgroup\$ – Dada Sep 1 '16 at 10:47
  • \$\begingroup\$ So you're using @ for scalar variable name; &1 for "and"ing the last bit to check if it's even (and not a backreference as I thought). Ok understood now, thanks. \$\endgroup\$ – Al.G. Sep 1 '16 at 10:54
  • \$\begingroup\$ Nice solution. You can gain a few more bytes by using $|-- as a toggle instead of $@++%2 \$\endgroup\$ – Ton Hospel Sep 1 '16 at 15:19
1
\$\begingroup\$

Bash + coreutils, 106 bytes:

for i in `seq $1`;{ printf "I %s %s " `((i%2>0))&&echo hate||echo love` `((i==$1))&&echo it.||echo that`;}

Simply creates a sequence starting at 1 up to and including the input integer using the seq built-in, and then iterates through it one by one, first outputting hate if the value of the iteration variable, i, is not divisible by 2 and love otherwise. In the same iteration, it then chooses to output that if i is not equal to the input value, and it. otherwise.

Try It Online! (Ideone)

\$\endgroup\$
  • \$\begingroup\$ Better put the command substitutions directly in printf's string and use no format specifiers. Is pointless to compare whether i%2 is greater than 0. I you reverse the commands in the list, you can use less than comparison instead of i==$1: for i in `seq $1`;{ printf "I `((i%2))&&echo hat||echo lov`e `((i<$1))&&echo that||echo it.` ";}. By the way, we usually label such solutions as Bash + coreutils, because the use of seq. \$\endgroup\$ – manatwork Sep 2 '16 at 13:46
1
\$\begingroup\$

///, 60 57 bytes

/!/I hate //T/that //
/it.//00/!TI love T//Tit./it.//0/!/

-3 bytes thanks to m-chrzan

Input in unary with trailing new line.

Try it online!

\$\endgroup\$
  • \$\begingroup\$ You could add /T/that / to the beginning and replace all instances of that with T. \$\endgroup\$ – m-chrzan Sep 21 '16 at 22:24
0
\$\begingroup\$

R, 92 90 bytes

An R adaptation of @Leaky Nun's python answer. Working with strings in R is tedious as always.

n=scan();cat(rep(strsplit("I hate that I love that ","")[[1]],n)[6:(n*12)-5],"it.",sep="")

This could probably be golfed further though.

Edit: saved 2 bytes by changing:

[1:((n*12)-5)]to [6:(n*12)-5]

\$\endgroup\$
  • \$\begingroup\$ It works out better to loop instead; see my alternative R solution. \$\endgroup\$ – JDL Aug 31 '16 at 14:06
0
\$\begingroup\$

C, 96 Bytes

c;f(i){printf("I hate");for(;c<i+1/2-1;c++)printf(" that I %s",c&1?"hate":"love");puts(" it.");}

I didn't see the above solution from Releasing Helium Nuclei which is better.

\$\endgroup\$
0
\$\begingroup\$

MATL, 37 bytes

:"2@o3]Qv'hate I that it. love'Ybw)Zc

Try it online!

Explanation

The code is based on the following mapping from numbers to strings:

0: 'love'
1: 'hate'
2: 'I'
3: 'that'
4: 'it.'

The program pushes numbers to the string in groups of three: 2, 0, 3; then 2, 1, 3; then 2, 0, 3; ... as many times as the input n. After that, the final 3 is transformed into a 4, the mapping is applied to transform numbers to strings, and the strings are joined using space as separator.

:                         % Input n implicitly. Push range [1 2 ... n]
"                         % For each
  2                       %   Push 2
  @o                      %   Iteration index modulo 2: pushes 0 or 1
  3                       %   Push 3
]                         % End
Q                         % Add 1 to the last 3
v                         % Concatenate stack contents into a numeric column vector
'hate I that it. love'    % Push this string
Yb                        % Split at spaces. Gives a cell array of five strings
w                         % Swap to move numeric vector to top
)                         % Index cell array of strings with that vector. Indexing
                          % is 1-based and modular, so 0 refers to the last string.
                          % This gives a cell array of (repeated) strings
Zc                        % Join those strings by spaces. Display implicitly
\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 68 bytes

f=(n,i)=>n?(i?' that I ':'I ')+(i&1?'love':'hate')+f(n-1,-~i):' it.'

document.write('<pre>'+[ 1, 2, 3, 4, 10, 100 ].map(c=>c+': '+f(c)).join`\n`);

\$\endgroup\$
0
\$\begingroup\$

C#, 85 83 bytes

string f(int n,int m=2)=>"I "+(1>m%2?"hat":"lov")+(m>n?"e it.":"e that "+f(n,m+1));

Recursively constructs the string, using an optional parameter to keep track of which hate/love and how many to append.

-2 bytes from this tip for checking the evenness/oddness of a number.

No optional parameter solution, 87 86 84 bytes

string h(int n)=>"I "+(0<n?"hat":"lov")+(2>n&-2<n?"e it.":"e that "+h(0<n?~n+2:~n));

This one does the same thing except determines which hate/love to append based on whether the parameter is positive or negative. Each iteration the parameter approaches zero, alternating sign.

\$\endgroup\$
0
\$\begingroup\$

Thue, 100 bytes

@::=:::
>##::=>$.
$::=~I hate that I love 
>.#::=>&#
&::=~that 
>#<::=~I hate it.
>.<::=~it.
::=
>@<

Takes input as unary. (A string of n #s)

\$\endgroup\$
0
\$\begingroup\$

Pyke, 36 bytes

2/"I hate ""I love "]*"that "J"it."+

Try it here!

2/                                   -    input/2
                     *               -   ^ * v
  "I hate ""I love "]                -    ["I hate ", "I love "]
                      "that "J       -  "that ".join(^)
                              "it."+ - ^+"it."

Also 36 bytes

12*5+.daෆ   ű   l5d+12"I ":Q*<"it."+

Try it here! (Link uses X instead of I, this should work for the same amount of bytes offline where you can literally use those bytes. Online \r gets automatically replaced with \n)

\$\endgroup\$
0
\$\begingroup\$

><> (Fish), 82 Bytes

' I'oov.2coo<;oooo' it.'<
'ahv'v>'et'
oop26<^ooooo^o' that I '^!?:-1oo
'ol^'^>'ev'

Doubt it's very efficient, but it seems to more or less work. Input is via the starting stack, which makes the score 85 Bytes if you include the size of the -v argument required to do so.

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Lua , 75 Bytes

n=io.read();print(('I hate that I love that '):rep(n):sub(1,n*12-5)..'it.')
\$\endgroup\$
  • 1
    \$\begingroup\$ Instead of static methods better use instance methods: ('I hate that I love that '):rep(n):sub(1,n*12-5). And would look nicer if you concatenate "it." to the end, because print() outputs its parameters separated by tab. \$\endgroup\$ – manatwork Sep 2 '16 at 14:15
  • 1
    \$\begingroup\$ The ';' between io.read() and print is unneeded, and arg[2] is a valid input method for lua scripts, which is the first command line argument. \$\endgroup\$ – ATaco Sep 21 '16 at 0:54
0
\$\begingroup\$

///, 68 bytes

/@/1\/#love //%/hate//#/that I //%1i/% i//I %1/I % //1@#% //@/I %1it.

Input in unary - add more 1s in the last section.

Try it online!

\$\endgroup\$
0
\$\begingroup\$

dc, 75 bytes

?[1-lbP[I lov]P]sa[e that ]sb[[e it.]Pq]sc[1-[I hat]Pd2%1=ad1>clbPlxx]dsxx

We're really just printing one chunk of string at a time here, and not leaving any garbage on the stack. This is great, we don't need to waste any bytes dealing with a register for our counter.

?                              #Input, works as our decrement counter
[1-lbP[I lov]P]sa              #Macro 'a' decrements our counter, prints string 'b', 
                               #then prints 'I lov'
[e that ]sb                    #String 'b'
[[e it.]Pq]sc                  #Macro 'c' prints the tail end of our message and quits
[1-                            #I'll unfold our main macro here; first step is to 
                               #decrement our counter
   [I hat]P                    #We always start by hating 'it,' no conditional needed
           d2%1=a              #Check the oddness of our counter; execute 'a' if odd
                 d1>c          #Check our counter; If we're done, execute 'c'
                     lbPlxx]   #Otherwise, print 'b' again and start this macro ('x') over
dsxx                           #Stores the above macro as 'x' and runs it.
\$\endgroup\$
0
\$\begingroup\$

Julia, 91 Bytes

Thought I add a julia solution:

f(N)=string("I hate ",join(["that I love that I hate " for _ in 1:N-1])[1:12*(N-1)],"it."))
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.