# Loves me, Loves me not

This simple kids' game is old, but still popular. Since we are living in 21st century now, let's digitize it!

# Specification

Program must take no input, unless you are using a language that can't generate random seed - in that case you are allowed to take the seed as an input. Your task is to write a program that will output randomly a total of 3 to 20 lines inclusive: "Loves me..." and "Loves me not..." in turns, as in the game (and one additional line; keep reading).

However, there are some restrictions. Each line should be followed by newline. The first line must be "Loves me...". The last line (either "Loves me" or "Loves me not") should end with exclamation mark or a single dot, respectively. After the last line, you need to output either a heart( <3 ) or a broken heart ( </3 ) in the new line, depending whether "Loves me!" or "Loves me not." was the last sentence.

Trailing whitespace are allowed.

# Example Output

Output:

Loves me...
Loves me not...
Loves me...
Loves me not...
Loves me!
<3

Another output:

Loves me...
Loves me not...
Loves me...
Loves me not.
</3

## This is the code-golf, so the shortest entry wins!

Also, my first challenge :) Good luck!

• Are there any restrictions on the distribution of the number of lines, i.e., should it be uniformly random, or is it enough that all lengths between 3 and 20 have a positive probability? – Zgarb Sep 15 '15 at 15:13
• I didn't think about this, but I'd say that any distribution is fine - so they don't have to be uniformly random. – MatthewRock Sep 15 '15 at 15:14
• Is it 3 to 20 ([3, 20)) or 3 up to including 20 ([3, 20])? – orlp Sep 15 '15 at 15:15
• @MatthewRock What if the language we want to use can't seed a random number on their own? Can the user supply a random seed? – mınxomaτ Sep 15 '15 at 15:35
• @minxomat Whatever, it's just a game. Go on, changed the rules. – MatthewRock Sep 15 '15 at 18:25

# Pyth, 54535150 48 bytes

pj+*3\.bm+W~!Z"Loves me"" not"+3O18@".!"Z%hZ"</3

• %2tWZ"<</33 for the heart printing saves 1. Not convinced this is the best way though. – FryAmTheEggman Sep 15 '15 at 15:32
• @FryAmTheEggman Made it save two. – orlp Sep 15 '15 at 15:36
• Merging the last two strings together saves another one, but I had to switch back to my %. – FryAmTheEggman Sep 15 '15 at 15:43
• @".!"Z%hZ"</3 saves two bytes – Jakube Sep 15 '15 at 20:00
• Since there has been no entry for few days, I'm accepting this answer. Congratulations! – MatthewRock Sep 24 '15 at 15:02

# CJam, 5350 49 bytes

Thanks to Dennis for saving 1 byte.

Imr3+{"Loves me"X!:X" not"*'.3*N}*&"!."X=N'<'/X*3


Test it here.

## Explanation

The code just dumps the string in bits and pieces onto the stack, which is printed automatically at the end of the program:

Imr3+         e# Generate a random number in [3,20]
{             e# Execute this block that many times.
"Loves me"  e#   Push "Loves me", we always need that.
X!:X        e#   Toggle X (initially 1) between 0 and 1 and leave it on the stack.
" not"*     e#   Repeat " not" that many times, removing it on every other line.
'.3*N       e#   Push "..." and a newline.
}*
&             e# Set intersection of "..." and newline, turning them into an empty array.
"!."X=        e# Select "!" or "." based on the last value of X.
N'<           e# Push a newline and "<".
'/X*          e# Include "/" or not depending on the last value of X.
3             e# Push a 3.

• one could imagine CJam would've been developed exclusively for code-golf ^^ – larkey Sep 15 '15 at 19:55
• @larkey but it is... – MatthewRock Sep 15 '15 at 21:14
• @larkey CJam is derived from GolfScript, and GolfScript (as its name implies) is designed for golfing. – Chris Jester-Young Sep 16 '15 at 19:16
• @ChrisJester-Young it was ment a bit tongue-in-cheek ;-) – larkey Sep 16 '15 at 21:49

# Brainfuck, 2766 bytes (currently invalid)

Just because. I'll add an ungolfed version later.

### Code

>+<+[>[>[-]+<-]>[<+>>+[->,----------[<+>[>>>>>>>>>+<<<<<<<<<-]>>>>>>>>>[>+<<<<<<<<<<+>>>>>>>>>-]<<<<<<<<<[>>>>>>>>>+<<<<<<<<<-]]<]<-]>>>>>>>>>>>>>>[<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>-]<<<<<<<<<<<<<<<[>[-]+<-]>[<+>>>>>>>>>>>>[<<<<<<<<<<+>>>>>>>>>>-]>[<<<<<<<<<<+>>>>>>>>>>-]<<<<<<<<+++++++[<+++++++++++>-]<[<<[>>>>>>>>>>+<<<<<<<+<<<-]>>>[<<<+>>>-]<<[>>>>>>>>>+<<<<<<<+>+<<<-]>>>[<<<+>>>-]<[>>>>>>>>+[<<<<<<<+>+>>>>>>-]<<<<<<[>>>>>>+<<<<<<-]+<[>-<[-]]>[>>>>>+<<<<<-]<<-]<-]++++++[>++++++++<-]>-[<<[>>>>>>>>>+<<<<<<<<+<-]>[<+>-]>-]<<<[-]>[-]+++++[<+++++>-]<[>>>>>>>>>>>+[<<<<<<<<<<+>+>>>>>>>>>-]<<<<<<<<<[>>>>>>>>>+<<<<<<<<<-]+<[>-<[-]]>[>>>>>>>>+<<<<<<<<-]<<-]++++++[>>>>>>>>>>+++++++++<<<<<<<<<<-]>>>>>>>>>>[<<+<<<<<<<<+>>>>>>>>>>-]<<<<<<<<<<[>>>>>>>>>>+<<<<<<<<<<-]>>>>>>>[-]>[<+<<<<<<<+>>>>>>>>-]<<<<<<<<[>>>>>>>>+<<<<<<<<-]>>>>>>>>>[-]++++++++++++++++++++<<[<<<+>>>-]>>[<<<<<<<<+>+<<+>>>>>>>>>-]<<<<<<<<<[>>>>>>>>>+<<<<<<<<<-]>>[>>[<+<<<+>>>>-]<<<<[>>>>+<<<<-]+>>>[<<->>>-<<<<->>>[-]]<<<[>>[-]+<<-]>>-]>>[>>>-<<<[-]]<<<[-]>>>>>>>>[-]<[>+<<<<<<<<<+>>>>>>>>-]<<<<<<<<[>>>>>>>>+<<<<<<<<-]>>>>>>>>>>>>[-]+++<<<[<<<<<+>>>>>-]>>>[<<<<<<<<<<<+>+<<+>>>>>>>>>>>>-]<<<<<<<<<<<<[>>>>>>>>>>>>+<<<<<<<<<<<<-]>>[>>[<+<<<+>>>>-]<<<<[>>>>+<<<<-]+>>>[<<->>>-<<<<->>>[-]]<<<[>>[-]+<<-]>>-]<[>>>>>>>>-<<<<<<<<[-]]>>>[-]>>>[<<<<<<<+>>>>>>>-]<<<<<<<[>>>>>>>-<<<<<<<[-]]>>>>>>>>>[<<<<<<<<<+>+>>>>>>>>-]<<<<<<<<[>>>>>>>>+<<<<<<<<-]<[>>>>>>>[-]-<<<<<<<[-]]>>>>>>>[>>>>>>+<<<<<<<<<<<<<<<->>>>>>>>>[-]]<<<<<<<<-]>>>>>>>>>>>>>>>[<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>-]<<<<<<<<<<<<<<<<[>[-]+<-]>[<+>>+++++++++++[>+++++++>++++++++++>+++++++++>+++>++++<<<<<-]>-.>+.+++++++.>++.<---.>>-.<<------.>.>>++...[-]<[-]<[-]<[-]<[-]<++++++++++.[-]>>>>>>>[-]>[<+<<<<<<<+>>>>>>>>-]<<<<<<<<[>>>>>>>>+<<<<<<<<-]>>>>>>>->[-]<[>+<-][-]>[<+<<<<<<<+>>>>>>>>-]<<<<<<<<[>>>>>>>>+<<<<<<<<-]>>>>>>>>>[-]<<[<<<<<<+>>>>>>-]->>[<<<<<<<<-<+>>>>>>>>>-]<<<<<<<<<[>>>>>>>>>+<<<<<<<<<-]>[>>>>>>+<<<<<<[-]]<->>>>>>>[<<<<<<<->>>>>>>-]<<<<<<<[>>>>>>>+<<<<<<<-]>>>>>>>[>>>>>>>>+<<<<<<<<<<<<<<<<<->>>>>>>>>[-]]<<<<<<<<-]<[>[-]+<-]>[<+>>++++++[>++++++++++<-]>.---------.[-]<<<-<->>-]>>>>>>>>>>>>>>>>[<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>-]<<<<<<<<<<<<<<<<<[>[-]+<-]>[<+>>+++++++++++[>+++++++>++++++++++>+++++++++>+++>++++<<<<<-]>-.>+.+++++++.>++.<---.>>-.<<------.>.>.<<+.+.+++++.>>>++...[-]<[-]<[-]<[-]<[-]<++++++++++.[-]>>>>>>>[-]>[<+<<<<<<<+>>>>>>>>-]<<<<<<<<[>>>>>>>>+<<<<<<<<-]>>>>>>>->[-]<[>+<-][-]>[<+<<<<<<<+>>>>>>>>-]<<<<<<<<[>>>>>>>>+<<<<<<<<-]>>>>>>>>>[-]<<[<<<<<<+>>>>>>-]->>[<<<<<<<<-<+>>>>>>>>>-]<<<<<<<<<[>>>>>>>>>+<<<<<<<<<-]>[>>>>>>+<<<<<<[-]]<->>>>>>>[<<<<<<<->>>>>>>-]<<<<<<<[>>>>>>>+<<<<<<<-]>>>>>>>[>>>>>>>+<<<<<<<<<<<<<<<<->>>>>>>>>[-]]<<<<<<<<-]<[>[-]+<-]>[<+>>++++++[>++++++++++<-]>.-------------.++++.<<<<->>-]<<]


### Pseudocode

loop
get a random byte
until random byte is >2 and <21

point to byte
[
output "Loves me..."
decrease byte by 1
if byte is 0
output "<3"
exit
eif
output "Loves me not..."
decrease byte by 1
]
output "</3"


### Sample

When run, the program enters an interactive session waiting for input. Input should be a number. This number is used as a seed.

Seed: 1 (random number is 5, takes 218,168,042 operations)

1
Loves me...
Loves me not...
Loves me...
Loves me not...
Loves me...
<3


Seed: 3 (random number is 20, takes 463,253,048 operations)

3
Loves me...
Loves me not...
(...)
Loves me...
Loves me not...
</3


I'd suggest that you do not seed with 6, as it takes 2,105,900,375 iterations to compute the result :).

### Compiling / Running

You need a fast interpreter for this. No online interpreter I've tested could handle the execution speed. The ips (iterations per second) should be more than 100,000,000. So I came up with another solution.

This is a Brainfuck to C compiler written in Brainfuck. You can use any online interpreter to transpile my code to pure C. I suggest using brainfuck.tk. Paste my code in the stdin input, past this code in the code input:

+++[>+++++<-]>>+<[>>++++>++>+++++>+++++>+>>+<++[++<]>---]>++++.>>>.+++++.>------.<--.+++++++++.>+.+.<<<<---.[>]<<.<<<.-------.>++++.<+++++.+.>-----.>+.<++++.>>++.>-----.<<<-----.+++++.-------.<--.<<<.>>>.<<+.>------.-..--.+++.-----<++.<--[>+<-]>>>>>--.--.<++++.>>-.<<<.>>>--.>.<<<<-----.>----.++++++++.----<+.+++++++++>>--.+.++<<<<.[>]<.>>,[>>+++[<+++++++>-]<[<[-[-<]]>>[>]<-]<[<+++++>-[<+++>-[<-->-[<+++>-[<++++[>[->>]<[>>]<<-]>[<+++>-[<--->-[<++++>-[<+++[>[-[-[-[->>]]]]<[>>]<<-]>[<+>-[<->-[<++>-[<[-]>-]]]]]]]]]]]]]<[-[-[>+<-]>]<[<<<<.>+++.+.+++.-------.>---.++.<.>-.++<<<<.[>]>>>>>>>>>]<[[<]>++.--[>]>>>>>>>>]<[<<++..-->>>>>>]<[<<..>>>>>]<[<<..-.+>>>>]<[<<++..---.+>>>]<[<<<.>>.>>>>>]<[<<<<-----.+++++>.----.+++.+>---.<<<-.[>]>]<[<<<<.-----.>++++.<++.+++>----.>---.<<<.-[>]]<[<<<<<----.>>.<<.+++++.>>>+.++>.>>]<.>]>,]<<<<<.<+.>++++.<----.>>---.<<<-.>>>+.>.>.[<]>++.[>]<.>[.---->.---,....]


gcc.exe -c main.c -o main.o
gcc.exe main.o -o loveme.exe


You can also run a copy of the C code online here: via. CodingGround.

### Optimizations

There is still some work to do, but the cell re-use is almost optimal.

### Remarks

You can use words or phrases as a seed:

Programming Puzzles & Code Golf
Loves me...
Loves me not...
Loves me...
Loves me not...
Loves me...
Loves me not...
Loves me...
Loves me not...
Loves me...
Loves me not...
Loves me...
Loves me not...
Loves me...
Loves me not...
Loves me...
Loves me not...
Loves me...
<3

• +1 for having the audacity to write a PRNG in Brainfuck ... – AdmBorkBork Sep 15 '15 at 19:36
• @TimmyD There are better ways to write PRNGs in BF, but most of them are time based (run the program, and stop execution at some point, then read memory), but that would require user interaction and two separate programs, which is against the rules. – mınxomaτ Sep 15 '15 at 19:43
• Nice pseudocode. More people should do that, especially since half the golfing languages are basically unreadable if you don't know them. – The_Basset_Hound Sep 16 '15 at 1:54
• Unfortunately your output is wrong. Last "Loves me" should end with an exclamation point(so, "Loves me!"), and "Loves me not" should end with single dot("Loves me not."). – MatthewRock Sep 16 '15 at 14:06
• Can we have some pseudocode of the RNG? – Beta Decay Sep 19 '15 at 21:27

# Javascript (ES6), 11910499 98 bytes

for(i=new Date%18+3,s=i&1?!
<3:.
</3;i--;)s=...
Loves me+(i&1?' not':'')+s

• Good one! It may be shorter to use string concatenation for creating the heart, and possibly in the creation of each line. Mind if I use the new Date trick in my answer? – ETHproductions Sep 15 '15 at 18:42
• @ETHproductions Go for it, so long as you're fine with me using those hearts haha (and why didn't I use alert... for some reason I convinced myself arrow functions would be shorter, but needing return negates that...). I actually just got it down to 104 now with some other tricks as well =) – Mwr247 Sep 15 '15 at 18:46
• Dang... nice job :) I keep rearranging mine, but always end up at 104. – ETHproductions Sep 15 '15 at 18:58
• The breakthrough for me was combining the length/iteration variable by concatenating backwards, and defining the hearts in the initialization. I tried it a while back with little savings, but your heart simplification made it much more efficient. – Mwr247 Sep 15 '15 at 19:03
• Wait a minute... Trying this, I get Loves me not... Loves me... Loves me not! <3 and Loves me not... Loves me... Loves me not... Loves me. </3. I think you'll have to change one of the conditionals to fix this. EDIT: Oh, just switch the '' and ' not' in the fourth line. – ETHproductions Sep 15 '15 at 19:07

# Python, 147

from random import*;t=randint(3,20)
print"\n".join("LLoovveess  mmee  n o t"[i%2::2].strip()+"..."*(i<t-1)for i in range(t))+"!.\n\n<<3/ 3"[t%2::2]


Uses the from random import* instead of import random and randint instead of randrange to save a few bytes. There's probably some bytes left to golf out.

• The alternation "LLoovveess mmee n o t"[i%2::2].strip() seems needlessly complicated. Can't you just do "Loves me"+~i%2*" not"? – xnor Sep 16 '15 at 4:17
• Even ["Loves me","Loves me not"][i%2] is more optimal, since you're now wasting chars on .strip() and a couple of spaces. But yes, use xnor's code – nitro2k01 Sep 18 '15 at 8:36

# Javascript (ES6), 110 102 bytes

a='';for(i=j=new Date%18+3;i--;)a+='Loves me'+(j-i&1?'':' not')+(i?...
:j&1?!
<3:.


This was a short but fun little challenge. It may be possible to shorten more. Thanks to Mwr247 for some byte-saving tricks!

Alternate version using repeat(), 105 bytes:

a='';for(i=j=new Date%18+3;i;)a+='Loves me'+' not'.repeat(j-i--&1)+(i?...
:j&1?!
<3:.


Darn JS 5+-char built-in names. Oh well. Suggestions welcome!

• Impressive condensing. I'm curious though, why the 18+3|0? – Mwr247 Sep 15 '15 at 18:58
• @Mwr247 Oh, duh, that was from when I used Math.random(). Guess it's not necessary now. – ETHproductions Sep 15 '15 at 18:59

# Perl, 85

print$_?'... ':'','Loves me',$c=$_%2?' not':''for 0..3+rand 18;print$c?'.
</3':'!
<3'


# Ruby, 91 bytes

(n=3+rand(18)).times{|i|puts"Loves me"+[""," not"][i%2]+(i<n-1?"...":i%2>0?".
</3":"!
<3")}


# Common Lisp 106 104 bytes

(format t"~{Loves me~[ not~]~#[~:*~[.~%</~;!~%<~]3~:;...~]~%~}"(subseq'#1=(1 0 . #1#)0(+ 3(random 18))))


This only works on lisps that don't check for a proper sequence (e.g. cmucl, sbcl, clisp) ccl will check for circularity and error out on default safety level. ecl will loop forever.

## Explanation:

#1=(1 0 . #1#) generates a circular list containing 1 and 0 and subseq is used to make a list of length [3,20] (this is the only non-portable part, as subseq is only required by the standard to work on proper (i.e. non-circular) lists).

Our format is now operating on a list of 1 0 1 0... of length [3,20]

### Explanation of format directives:

~{ iterates over this list

~[ followed by any number of ~; and terminated with ~] will select the Nth item, based on the value of the format argument. This is used here so that the first item in a ~[ will be the "loves me not" case and the second one the "loves me" case. Note that with ~[ a separator of ~:; selects a default case.

~#[ works like ~[ except the argument is the number of remaining arguments. 0 remaining arguments means we are at the end, the default case is to print ...

~:* backs up the argument list one position, which allows us to print the correct trailer.

• This was a group effort by the #lisp IRC channel. Many thanks to phf for the clever iterative format-string and the subseq hack. – Jason Sep 16 '15 at 17:28

# Julia, 98 bytes

r=rand(3:20)
for i=1:r println("Loves me"*(i%2>0?" not":"")*(i<r?"...":i%2>0?".\n</3":"!\n<3"))end


Ungolfed:

# Define a random number 3 ≤ r ≤ 20
r = rand(3:20)

for i = 1:r
# The loveless lines occur when i is even
println("Loves me" *
(i % 2 > 0 ? " not" : "") *
(i < r ? "..." : i % 2 > 0 ? ".\n</3" : "!\n<3"))
end


# UNIX shell, 193 bytes

t=$(seq 2 19|shuf|head -1) l=t p=... while [$t -ge 0 ];do
case $l:$t in t:0)p=!;h=\<3;;f:0)p=.;h=\</3;;esac
case $l in t)l=f;n=;; f)l=t;n=\ not;;esac t=$((t-1))
echo Loves me$n$p
done
echo $h  # Java, 210209203200 177 bytes • flipped i%2==0 to i%2<1 • trimmed { ... } braces for for-loop, moved e declaration to loop • re-ordered conditionals • removed modifiers and unnecessary parentheses, reworked Random usage and increment for i Note: newline is added below for formatting on this site, the count above is for a single line. class F{public static void main(String[]a){for(int e=3+(int)(Math.random()*18),i=0;++i<=e;) System.out.println("Loves me"+(i%2>0?i<e?"...":"!\n<3":" not."+(i<e?"..":"\n</3")));}}  Ungolfed: class F { public static void main(String[] a) { for (int e = 3 + (int) (Math.random() * 18), i = 0; ++i <= e; ) System.out.println("Loves me" + (i % 2 > 0 ? i < e ? "..." : "!\n<3" : " not." + (i < e ? ".." : "\n</3"))); } }  • You can save 13 bytes by removing public. – Luminous Sep 16 '15 at 14:12 • @Luminous I'll still need to keep the one for main() though... – h.j.k. Sep 16 '15 at 14:55 • @TimmyD I second that. – RK. Sep 16 '15 at 22:39 # C, 123, 121, 109 106 characters (108 bytes) (with a little ♥♥♥cheating♥♥♥) O;main(o){for(o=time(O)%18+3;o-O++;printf("Loves me%s%s\n",O&1?"":" not",o-O?"...":O%2?"!\n♥":".\n</3"));}  There's also a broken heart Unicode point at 1f494, but I had difficulties finding a font which implements it. • This shows 120 characters and 122 bytes... – AdmBorkBork Sep 16 '15 at 18:14 • I don't think you need O=0, because C auto-initialize ints to 0? – FryAmTheEggman Sep 16 '15 at 18:14 • @FryAmTheEggman Good find! In a previous version I had O in main(o,O) where it had to be initialized. – Jens Sep 16 '15 at 18:18 • Nice, I like it! I didn't think of using time as a random number... Clever! – MatthewRock Sep 16 '15 at 18:21 • @MatthewRock If you think about it, all the other program using srand(time(0)) will change their answer with the same frequency. The srand is completely useless :-) – Jens Sep 16 '15 at 18:22 # Python 2, 161159156 144 bytes from random import*;a=randrange(3,21) for i in range(a):print'Loves me'+i%2*' not'+('...'if i!=a-1 else'.'if i%2 else'!') print['<3','</3'][i%2]  It's 39 bytes just to get the random number. A big thank you to muddyfish, fryamtheeggman, and orlp for their help. # PYG, 109 bytes a=RR(3,21) for i in R(a):P('Loves me'+i%2*' not'+('...'if i!=a-1 else'.'if i%2 else'!')) P(['<3','</3'][i%2])  • You can do the range statement in a single line. you can also do import random as r – Blue Sep 15 '15 at 16:07 • you can also put the contents of the last print statement onto the line above. – Blue Sep 15 '15 at 16:10 • I think you can change print'</3'if i%2 else'<3' to print['<3','</3'][i%2] to save 3 bytes. – Kade Sep 15 '15 at 16:20 • Yes indeed I can; thanks! – Celeo Sep 15 '15 at 16:22 • Thanks! Interestingly, import random as r;a=r.randrange(3,21) and import random;a=random.randrange(3,21) are the same length. – Celeo Sep 15 '15 at 16:24 # PowerShell, 121119 111 Bytes $i=2..19|Random;1..$i|%{"Loves me$(if(!($_%2)){" not"})..."};"Loves me$(if(!($i%2)){"!n<"}else{" not.n</"})3"  Edit--actually shorter to explicitly include "Loves me" rather than declaring $l

Edit2--forgot that I can golf for() loops by pipelining...durr...

Not too shabby. Uses inline code execution blocks $(...) to dynamically adjust the printed string as we're for()-looping. Note that because this uses an implicit Get- in front of Random to save a couple bytes, this may operate extremely slowly on certain PowerShell versions. Reference Expanded below for clarification: # Create a collection of (2,3,4,...18,19) and pipe it as input to Get-Random$i = 2..19 | Get-Random

# Create a collection of (1,2,...$i-1,$i) and pipe it to seed a ForEach-Object loop
1..$i | ForEach-Object { if(!($_%2)) {
# If the input number is even, we're on an even line
Write-Output "Loves me not..."
}
Else {
# The input number is odd
Write-Output "Loves me..."
}
}
If(!($i%2)) { # Our random number is odd Write-Output "Loves me!" Write-Output "<3" } Else { # Our random number is even Write-Output "Loves me not." Write-Output "</3" }  # C++, 210193184 168 bytes In C++.. because.. Why not? :) #include <iostream> main(){auto&c=std::cout;srand(time(0));int i,j=3+rand()%18;while(i++<j)c<<"Loves me"<<(i%2?"":" not")<<(i==j?"":"...\n");c<<(j%2?"!\n<3":".\n</3");}  Live: 210 193 184 168 Just hope that any of my changes are not platform dependent. Thanks to Ben Voigt for the help. Also, thanks to all the comments, they were very helpful. • Humn.. just realize its 3 to 20. I will fix that later. Probably will add 2 more bytes... j=3+(int)(rand()*17.0/RAND_MAX) – wendelbsilva Sep 15 '15 at 19:33 • You can save a lot by replacing #define c cout and using namespace std; by auto&c=std::cout; – Ben Voigt Sep 15 '15 at 22:55 • Also save some with int i=0,j=rand()*20.0/RAND_MAX;while(i<j) – Ben Voigt Sep 15 '15 at 23:00 • Hello, found a bug: Last line should be "Loves me!", not "Loves me." – MatthewRock Sep 16 '15 at 10:55 • I'd say it's okay - C and C++ are similar. And right now this code is longer than Java... – MatthewRock Sep 16 '15 at 15:01 # Groovy, 110 bytes A groovy kind of love: int r=Math.random()*18;print((0..r+2).collect{"Loves me"+" not"*(it%2)}.join('...\n')+['!\n<3','.\n</3'][r%2])  # Python 2, 117 bytes from random import* n=randint(3,20) print"...\n".join("Loves me"+i%2*" not"for i in range(n))+[".\n</3","!\n<3"][n%2]  Observe that every Loves me( not)? is followed by ... and a newline, except for the last one. So this looks like a job for join. • A bit late but ".!\n\n<</33"[n%2::2] is 2 bytes shorter. – FryAmTheEggman Sep 17 '15 at 20:18 • @FryAmTheEggman Yeah, I did see that but decided not to steal it from Loovjo. In the meantime, someone else has posted exactly that solution. [shrug] – DLosc Sep 17 '15 at 22:16 • I hadn't noticed someone else posting it, but I am pretty sure my comment was the first that had it in it, so you can use it if you want :P – FryAmTheEggman Sep 17 '15 at 22:27 # R, 141132128114111 109 bytes ### Code k=sample(3:23,1);for(i in 1:k)cat("Loves",c("me not...\n","me...\n","me not.\n</3","me!\n<3")[1+i%%2+2*!i<k])  ### Ungolfed k <- sample(3:23, 1) # Generates random "k" number from 3 to 23 for(i in 1:k) { # Loop this block increasing i from 1 until k by 1 cat # Concatenate and paste everything inside this block ("Loves", # Push "Loves" on every iterations of the loop c( # Create a vector of strings "me not...\n", # Push string to the index "1" of vector "me...\n", # to the index "2" "me not.\n</3", # to the index "3" "me!\n<3" # to the index "4" )[1+i%%2 # Subset the vector by the index (1 or 2) +2*!i<k])} # if final iteration of loop then index += 2 (3 or 4)  I've took some inspiration from Eric Brooks code. Edit 1: Now the code correctly outputs the last punctuation as pointed out by Martin Edit 2: Changed the for loop to a sapply and included the hearts inside the last line string. Edit 3: Removed the {} and changed +(x==k)*2 to +2*!x<k Edit 4: Back to for loop and removed the () from (i%%2)+1 Edit 5: Wrote me 4 times and removed the sep="" # R, 119111 105 bytes x<-sample(3:20,1);cat(rep(c("Loves me...\n","Loves me not...\n"),x)[1:x]);cat(ifelse(x%%2==1,"<3","</3"))  Edits 1,2: Coding the two options explicitly is saving space. • You can save a byte by using = for assignment rather than <- and another by doing x%%2>0 in place of x%%2==1. Also note that this doesn't handle the last line correctly; there should be a . or ! rather than .... (See example output in the question.) – Alex A. Sep 15 '15 at 20:43 • @Alex A. You don't need x%%2>0 either; just x%%2 – Flounderer Sep 15 '15 at 22:29 • Good points, thanks. I need to go back and fix the ending – Eric Brooks Sep 16 '15 at 14:50 # C 226 bytes #include<stdio.h> #include<stdlib.h> #include<time.h> void main(){srand(time(NULL));int i=rand()%18+3;int j;for(j=0;j<i;j++)printf("Loves me%s%s\n",(j%2)?" not":"",(j==i-1)?(j%2)?".":"!":"...");printf("<%s3\n",(j%2)?"":"/");}  (With formatting) #include <stdio.h> #include <stdlib.h> #include <time.h> int main() { srand(time(NULL)); int i = rand()%18 + 3; int j; for (j = 0; j < i; j++) printf("Loves me%s%s\n", (j % 2) ? " not" : "", (j==i-1) ? (j % 2) ? "." : "!" : "..."); printf("<%s3\n", (j%2) ? "" : "/"); return 0; }  • Remove return type from main (-5 bytes), make i and j global with default type (-8 bytes, -3 more because of default 0 in j), use 0 instead of NULL (-3). Other things - use only one variable and make the loop counting down maybe. Import stdio is not usually needed when golfing. – aragaer Sep 16 '15 at 10:15 # Python 2, 115 bytes from random import* n=randint(2,20) print'...\n'.join('Loves me'+i%2*' not'for i in range(n))+'.!\n\n<</33'[n%2::2]  # PHP, 191187146 165 Bytes $x=rand(5,22);for($i=2;++$i<=$x;){echo"\nLoves me";if($i%2<1)echo" not";if($i<$x)echo"...";if($i==$x&&$i%2<1){echo".\n</3\n";}elseif($i==$x&&$i%2>0){echo"!\n<3\n";}}


Ungolfed:

$x=rand(5,22); for($i=2;++$i<=$x;){
echo "\nLoves me";
if($i%2<1) echo " not"; if($i<$x) echo "..."; if($i==$x &&$i%2<1){
echo ".\n</3\n";
}
elseif($i==$x && $i%2>0){ echo "!\n<3\n"; } }  48,49 bytes for pyth and cjam ... wow :) • Changed$i%2==0 to $i%2<1 (x2) and$i%2!=0 to $i%2>0 (x2) – Marek Bettman Sep 16 '15 at 21:48 • turns out ternary operators are not the best answer at all times :) – Marek Bettman Sep 16 '15 at 22:02 # mSL, 178176156 154 bytes Edit 1: Changed == 0 to < 1 Edit 2: Removed unnecessary whitespace, thanks AlexA! Edit 3: Removed parentheses alias l { var %n 1 while %n <=$rand(3,20) {
var %m $+(Love me,$iif($calc(%n % 2) < 1,$chr(32) $+ not),...) echo %m inc %n } echo$iif(n isin %m,</3,<3)
}

• Your solution is currently 176 bytes, not 177. Is all of the whitespace necessary? If not, you could shorten your code by a significant amount simply by removing unneeded whitespace. – Alex A. Sep 16 '15 at 18:12
• @AlexA. Oh don't know why I wrote 177, and thanks for pointing out the necessity of whitespace, it is indeed not needed! – Denny Sep 16 '15 at 22:45

## Perl, 97 bytes

$_='She loves me... 'x(3+rand 18);s/(me.*?)me/$1me not/gs;s/e...
$/e! <3/;s/t...$/t.
<\/3/;print


$_="She loves me...\n"x(3+rand 18); s/(me.*?)me/$1me not/gs;
s/e...$/e!\n<3/; s/t...$/t.\n<\/3/;
print


# Hassium, 265 Bytes

func main(){rnd=new Random();times=rnd.next(3,21);println("Loves me...");for(x=0;x<times-1;x++){if(x%2==0)println("Loves me not...");else println("Loves me...");}if((times-1)%2==0){println("Loves me not.");println("</3");}else{println("Loves me!");println("<3");}}


• Your solution is currently 458 bytes, not 523. You can better your score by removing unnecessary whitespace and shortening variable names. See the other Hassium solution for examples. – Alex A. Sep 16 '15 at 18:16
• As I noted on the other Hassium answer, the random number generator seems to be extremely biased. I ran this 500 times with the latest version and only got two </3. – Dennis Sep 16 '15 at 20:05
• +Dennis The Random generator is built directly on top of the C# Random number generator. See: github.com/HassiumTeam/Hassium/blob/master/src/Hassium/… – Jacob Misirian Sep 16 '15 at 21:19
• It doesn't seem to get seeded correctly. If I execute rnd = new Random();rnd.next(0,2); 1000 times, the distribution is OK. However, if I execute rnd = new Random(); once and rnd.next(0,2); 1000 times, I always get exactly 533 0s and 467 1s. – Dennis Sep 16 '15 at 21:53

## C# (160)

The code is inspired by the answer from h.j.k., credit goes to him.

class P{static void Main(){for(int e=3+new Random().Next(0,18),i=0;++i<=e;)Console.WriteLine("Loves me"+(i%2>0?i<e?"...":"!\n<3":" not."+(i<e?"..":"\n</3")));}}


Ungolfed:

class P
{
private static void Main()
{
for (int e = 3 + new Random().Next(0, 18), i = 0; ++i <= e;)
Console.WriteLine("Loves me" + (i % 2 > 0 ? i < e ? "..." : "!\n<3" : " not." + (i < e ? ".." : "\n</3")));
}
}


## Lua, 137 132 bytes

Probably can be golfed a lot more, but here it is for now:

t=math.random(3,20)for i=1,t do io.write(i%2==0 and"Loves me"or"Loves me not")print(i==t and(i%2==0 and"!\n<3"or".\n</3")or"...")end


Code explanation and ungolfed:

t=math.random(3,20) --Generates a random number between 1 and 30. We need to assign it to a variable to check if the loop is over later.
for i=1,t do
io.write(i%2==0 and"Loves me"or"Loves me not") --If i%2 is 0 write without a newline Loves me, if not print Loves me not.
print(i==t and (i%2==0 and"!\n<3" or ".\n</3") or "...") --If it is not the end of the loop, put ..., else if we ended on an even print ! a newline, and then a heart, but if we ended on an odd put ., a newline and a broken heart :(
end


Edit: Chopped off some whitespace.

# Jelly, 55 bytes (non-competing?)

“¢zḞzƘFq»,;¥“ not”ṁ18X+2¤j“...¶”µċ⁷Ḃ©”/ẋ;3⁾¶<;®ị⁾.!¤;⁸;


Try it online!

As usual Jelly sucks with strings.

# PowerShell, 85 88 bytes

+3 bytes thanks Veskah: That's a good point.

0..(1..19|Random)|%{($l='Loves me')+' not'*($n=$_%2)+'...'}$l+('!
<3',' not.
</3')[!\$n]


Try it online!

• This can generate "Loves me, Loves me not </3", which, based on how I read the specs, is below the minimum number of lines. – Veskah Mar 6 '19 at 14:36
• Indeed of *3* to 20 lines inclusive. Thanks! – mazzy Mar 6 '19 at 15:48