text:
Tips for golfing in Brachylog
Brachylog is a language that's beginning to rise in prominence in code-golfing recently (and just received a major update with a terser syntax). Like Prolog, it has the advantage that it can often solve a problem (typically via brute force) merely from a sufficiently accurate description of what a problem looks like, a feature that means that on the right sort of challenge, it's often comparable to the top golfing languages (and has been known to beat Jelly from time to time).
What tips do you have for golfing (i.e. writing the shortest possible programs in) Brachylog? This is mostly looking for advice that's specific to Brachylog in particular, rather than advice that's applicable to a wide range of languages. (Tips about golfing in declarative languages in general might potentially be appropriate here, depending on how much application they'll have to languages other than Brachylog, although see also Tips for golfing in Prolog.)

Exploit nested predicates to create new variables
Brachylog has lots of special syntax cases to make its two special variables, ? (input / left parameter) and . (output / right parameter), terser to use. This means that if you don't need to access your predicate's ? and ., but do need to use variables, you can often save bytes via creating a nested predicate to use its ? and ..
As a simple example, consider a program that looks like this:
… A … ∧A … B … B …

This is a pretty common shape for a longer program; after all, there are lots of gaps that could contain anything. Suppose we have no need for ? or . inside the centre three gaps. Then we could rewrite it like this:
… { … & … . … } …

Here, the nested predicate's ? is serving the role of A, and its . is serving the role of B. We can observe that this is a byte shorter than the original code; changing AABB to {?.} has no change in terms of bytes, but this allowed us to simplify ∧? to the abbreviation &.
A related trick is to change
∧. … ?∧

to
~{ … }

(which is one byte shorter), although note that it's nearly always cheaper to get the caller to exchange the arguments instead (unless the predicate is called from at least three different places in the program, which is rare in Brachylog).

Split up length-2 predicates inside metapredicates
This is best explained by example. To remove the first and last elements of a list, we behead and knife it:
bk

If we wanted to perform this operation on every element of a list, we can use a map operation:
{bk}ᵐ

However, it's a byte shorter to split the predicate into two, and map each part separately:
bᵐkᵐ

The same trick can be used with quite a few metapredicates:
{bk}ᵐ  →  bᵐkᵐ
{bk}ˢ  →  bˢkˢ
{bk}ᶠ  →  bᶠkˢ
~{bk}  →  ~k~b

Note that for some metapredicates, like ᵘ, there's no general-purpose way to split it into two parts, but it may nonetheless be possible to find a decomposition that works for the specific task you're working on.

We do have an increment builtin... sometimes!
+₁ is the only reliable way to add 1 to something. However, under many circumstances, < does the job for a byte less--its output must be strictly greater than its input, so in the absence of external complications, its output will be the integer strictly greater than its input with the least absolute value.
Of course, this substitution can and will fall apart should further logic be employed, as well as in the case of non-integers (which are ceiled) and negative integers (which produce 0).

s isn't longest first, but ⊇ is
I wanted to title this "(Ab)use all choice orders at your disposal", but I couldn't think of any other cases of note.
Sometimes choice order is pretty important. Sometimes the choice order your program already has is precisely what you need, just as often it's not; in the case of s generating substrings in the order of largest-first prefixes of largest-first suffixes, it's not infrequent that you might wish it was simply largest first instead. Fortunately, ⊇ generates its sublists longest first, where every possible substring is included--there's just some other stuff you also don't want. However, s's choice order is no problem at all if you're using it to check substring existence, in a program structured something like ⊇. [...] &s.

Casting the empty list to the empty string
Sometimes, when working with strings, the algorithm we use might unify what we want with the empty list [], when we would rather want the empty string "".
We can cast the empty list to the empty string using ,Ẹ, which appends the empty string to its left variable (this is an exploit of the way , is implemented).
This also has the benefit that it does not do anything if the left variable is a string. So, if your program is
{
   some predicate that should always output a string,
   but actually outputs [] instead of "" in specific cases
}

Then
{
  some predicate that should always output a string,
  but actually outputs [] instead of "" in specific cases
},Ẹ

will work the way you want.

Single-element runs in a list
Consider this snippet:
ḅ∋≠

If the input is a list or string, the output is unified with a sublist/substring of length 1 that's not part of a longer run of equal elements.
It splits the list into blocks of equal elements and finds a block whose elements are all different.
To get the elements themselves instead of singleton lists, tack h to the end.
I used this construct here with o to find a character that occurs only once in the input string.

Failing on empty lists
Empty lists can come up often, and sometimes you need to fail when you see one. The obvious means to do so may be ¬Ė, or even l>0, but there exist quite a few one-byte alternatives:

b
k
h
t
∋
z

just off the top of my head. What inspired me to write this out is actually the discovery of a less obvious failure on an empty list: the metapredicate ⁿ, which one might expect to be vacuously successful on an empty input, fails instead. Metapredicates which produce failure on an empty list:

ⁿ
ᵛ
ᵉ
ᵈ (any list of length other than 2)
ʰ
ᵗ

The general idea to take away from this is that a lot of Brachylog's builtins that seem like they're just to produce an output from an input don't necessarily have an output for every conceivable input, which is more to our advantage than it is detrimental, and is (...usually) easy to think about once you're aware of it.


text:
Tips for golfing in tinylisp
tinylisp is, in its essence, a very stripped-down version of Lisp, as the name suggests. It was made by @DLosc for an "interpret this language" challenge, which can be found here. It features a small amount of builtins, which can be used to create practically anything.
There is a repository for the "official" tinylisp interpreter/documentation here, and it is available to try online here.
What tips do you have for golfing (creating the shortest program possible) in tinylisp? This question is looking for tips to golf specifically in tinylisp, not general tips that can be applied to any language.

Abuse builtins for type-checking
The official way to check the type of a value is with the type builtin, which returns one of Int, List, Name, or Builtin. However, (e(type x)(q Int)) is pretty verbose, and (type? x Int) with the library isn't too much shorter.
The good news here is that errors in tinylisp generally aren't fatal--they just print a warning to stderr and return () (nil). So under certain circumstances, we can use the one-letter builtins in unintended ways to perform ad-hoc type-checking. Supposing we have some value bound to the name x:

(a x 1) - truthy for all integers except -1; falsey for -1; error for any other type
(s x 1) - same, but replace -1 with 1
(a x 0) - same, but with 0
(t x) - truthy for lists with more than 1 element; falsey for nil and single-element lists; error for any other type
(h x) - truthy for nonempty lists with a truthy first element; falsey for nil and lists with a falsey first element; error for any other type
(c()x) - truthy for lists; error for any other type
(l()x) - truthy for nonempty lists; falsey for nil; error for any other type
(l 0 x) - truthy for positive integers; falsey for 0 and negative integers; error for any other type
(v x) - truthy for nonzero integers; falsey for 0 and nil; error for any list that's not a valid s-expression (including any nonempty list of integers); result varies for valid s-exprs and names

Even the string builtins, though longer, could be useful under certain circumstances:

(string x) - truthy for integers, builtins, names, and lists of integers (including nil); error for lists containing anything other than integers
(chars x) - truthy for nonempty names; falsey for empty name; error for any other type

For example, here's a function that adds all the integers in a ragged list such as (1 2 (3 4 (5) 6)):
(d S(q((L)(i L(i(e(type L)(q Int))L(a(S(h L))(S(t L))))0

(We could write (type? L Int) for the type-check if we loaded the library, but that costs more bytes unless we need the library for something else.)
By the time execution reaches (e(type L)(q Int)), we know that L is either a nonempty list or a nonzero integer. We want a test that's truthy if L is an integer and falsey/error if L is a list. (a L 0) fits the bill:
(d S(q((L)(i L(i(a L 0)L(a(S(h L))(S(t L))))0

But in this case, so does (v L). That's because:

v on any integer returns the integer unchanged, and we know the integer won't be zero, so it's always truthy
v on any list tries to evaluate the list as tinylisp code
Nil evaluates to itself, but we know the list is nonempty
A nonempty list evaluates as a function call, where the first element of the list is the function or macro. An integer isn't a valid function or macro; neither is nil; and a nonempty list will get evaluated as a function call, simply trying the same thing one layer down. Upshot: v will always error on a nonempty ragged list of integers.

Total savings: 13 bytes.
(d S(q((L)(i L(i(v L)L(a(S(h L))(S(t L))))0

Take advantage of parenthesis autocompletion
The tinylisp parser will fill in missing close parens at the end of each line, provided that each of your top-level expressions is on a single line (which it should be anyway for code golf). So instead of this:
(load library)(d D(q((M)(i(h M)(c(h(h M))(D(map t(t M))))()))))

you can write this, for a savings of 5 bytes:
(load library
(d D(q((M)(i(h M)(c(h(h M))(D(map t(t M))))(

(Just make sure that your test code in the header or footer is formatted the same way, or you may get some puzzling error messages.)

Use lambdas instead of full functions
To save a few bytes, you can make your answer a lambda instead of a full function:
Predecessor function:
(q (
  (n)
  (s n 1)))

Golfed:
(q((n)(s n 1)))

This is only useful if the function doesn't recurse.

Use the library
Although tinylisp itself has a small set of builtins, it also comes with a standard library that adds a lot of functionality. You can access any function in the library by running (load library).
The names of library functions/constants are not golfy like the builtins are, so some of them aren't worth it. For example, there's no need to load the library just to use inc or dec, since (a 1 x) is the same length as (inc x) and (a(some-expr)1) is shorter than (inc(some-expr)). For others, it depends on the use case: using reverse is probably shorter than reimplementing it yourself, but you may be able to restructure your code to avoid using it at all. Others, like *, are indispensable (multiplication isn't built in, and reimplementing it would be prohibitively long).
One drawback: there's not really any documentation besides just reading the code.

worth mentioning in the readme, maybe? I think i'll submit a PR with the docs for these

Try switching the order of expressions
When you have multiple atoms (names/integers) next to each other, they have to be separated by whitespace. In some cases, you can rearrange the expression to eliminate the whitespace. A common example is with addition:
(a 1(subexpression))
(a(subexpression)1)

A less obvious case is when you have a function with multiple arguments. Consider a function F with arguments (A B). If you're calling the function like this:
(F A(s B 1))

then you may be able to save a byte by taking the arguments as (B A) instead:
(F(s B 1)A)

(These particular examples only work if they're not at the end of a line; in that case, parenthesis autocompletion would make both options the same length. But there are instances where switching the order helps even at the end of a line.)
Reordering can be especially helpful with conditionals. Frequently, you will have a recursive function with a body structured like this:
(i(condition)(recursive call)(base case))

In some instances, you can save bytes by inverting the condition and reversing the order of the truthy and falsey branches:
(i(inv-condition)(base case)(recursive call))

For example, here's a function F that returns the length of a number's Collatz orbit:
(load library
(d F(q((N)(i(l 1 N)(a(F(i(odd? N)(a(* 3 N)1)(/ N 2)))1)0

If we change the condition (l 1 N) (truthy if N is greater than 1, falsey if N is 1 or less) to (l N 2) (truthy if N is less than 2, falsey if N is 2 or greater), we can switch the truthy and falsey branches and save a byte thanks to parenthesis autocompletion:
(d F(q((N)(i(l N 2)0(a(F(i(odd? N)(a(* 3 N)1)(/ N 2)))1

In this particular case, we can then save more bytes by rewriting (a(...)1 to (a 1(...:
(d F(q((N)(i(l N 2)0(a 1(F(i(odd? N)(a(* 3 N)1)(/ N 2

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Your very own "for" instruction, redux
Inspired by Sygmei's question, I'm interested in finding out what languages can "do this properly".
Your task is to write a "for loop" function / macro / instruction. The arguments should be:

an initializer
a test
an increment
a body

All of these are "pieces of code" and should be able to access variables in the context of the call. The body should be able to include multiple statements.
The aim is to have the fewest lexical tokens excluding comments, except that #define and friends (using a dumb preprocessor) are worth 50, and eval and friends (taking a string argument) are worth 100. Feel free to make your code readable with comments, whitespace and meaningful names.
You should include a "test harness" which is not counted towards length.
The C version definitely won't win:
// the do {...} while (0) idiom enables a code block to be a single C statement, so it can safely be followed by a semicolon
#define my_for(init, test, inc, body) do {  \
    init; \
    while (test) { \
        body; \
        inc; \
    } \
} while (0)

// test harness:
#include <stdio.h>

main()
{
    int i, total;
    my_for((i=1, total=0), i<=3, ++i, {printf("%d\n", i); total=total+i;});
    printf("total: %d\n", total);
}

Edit to add: the meaning of "lexical token" depends on your language. Here's how the scoring breaks down for my C version:
//[...]: 0
#define: 1 occurrence, 50 points
my_for: 1
(: 3
init: 2
,: 3
test: 2
inc: 2
body: 2
): 3
do: 1
{: 2
\: 6
;: 3
while: 2
}: 2
0: 1
TOTAL: 85

Unclear to me: scoring.  For example how would your c reference be scored?

I was actually going to do this challenge, but I ran into a fair number of difficulties in laying it out. I hope someone posts a well explained version; preferably normal code golf.

@DigitalTrauma does my edit clarify it sufficiently? If so how can I get the question re-opened? I can't tag all the on-hold-voters in this comment

The C scoring only makes it clear for C programs. It's very hard to define "tokens" for a wide range of languages. You either have to give up on the idea, or only allow a narrow range of languages (which is a whole different can of worms).

Can it be a lambda (anonymous function), or does it have to be a named function? 2) Is it okay to use the language's built-in for loop syntax in the implementation?

@Mego: Can you give an example where it is be hard to identify tokens? If it's just edge cases, can't they be resolved by asking the task author on a case by case basis?

@smls Asking the OP for every unclear case isn't reasonable. The rules need to be static and objective, not constantly being added to because edge cases come up that require the OP's discretion.

Name suggestion: My little For loop (sorry, mlp reference kek)

@smls 1. an anonymous function is fine. 2. reusing the builtin for-loop syntax is fine; reusing the builtin for-loop implementation is cheating.

I'm sorry, but this is still very confusing to me; in particular, it seems like we need judges to tell when something in a language counts as an eval or "dumb macro"; as in your comment in the TCL answer (which by no means is apparent to me reading your description here), or possibly how to judge the use of FORTH words.  Heck, I'm not even sure whether a traditional C preprocessor metaprogramming EVAL counts as a macro, or an eval, or both, or neither if using CPP as the language (despite your use of CPP in C as an example of dumb macros).

@HWalters re TCL answer: uplevel is like eval because it takes a string argument, and contains an interpreter for the language. Re CPP: I'm penalising C-style macros partly so we don't have to worry about it (and partly because they suck)

@HWalters just read it as "don't use these"

Okay, no chat, so cleaning up clutter, but I'll leave it at this.  (1) I really think you need to define "dumb preprocessor", and clearly state whether this involves the same language level parsing or not. (2) You also need to specify what counts as "eval" here; everything is a string until parsed, so this only becomes conflated with interpreted languages. (3) You might have to worry about CPP; I can pretty confidently say it won't win, but unless you forbid it it's not up to you whether there's a submission in it.  Hacking in CPP is actually a personal hobby of mine.

Python, 11 26 tokens:
def f(n, t, i, l):
    n()
    while t():
        l()
        i()

This is my first time doing atomic-code-golf, so forgive me if I got the token counting wrong.
EDIT: Hugh Allen informed me that I got the token counting wrong.

The thing is, [tag:atomic-code-golf] doesn't actually exist.

@feersum It has 44 questions.  How does it not exist?

That's a nice answer, but it's more than 11 tokens! See my edit for clarification (I hope)

I can't see your edit. Could you explain to me why it's more than 11 tokens?

All of those punctuation characters are tokens (though sometimes two punctuation chars can be a single token, eg. <=)

@HughAllen So 26 tokens?

@Challenger5 yes, 26 seems correct to me

Perl 6, 24 tokens
sub my-for (&init, &test, &inc, &body) {
    init;
    while (test) { body; inc }
}

Tokens:
while   1   keyword
sub     1   keyword
my-for  1   function name (declaration)
&init   1   function parameter (declaration)
&test   1   function parameter (declaration)
&inc    1   function parameter (declaration)
&body   1   function parameter (declaration)
init    1   function name (implicit call)
test    1   function name (implicit call)
inc     1   function name (implicit call)
body    1   function name (implicit call)
,       3   parameter list separator
;       2   statement separator
{       2   block opener
}       2   block closer
(       2   parameter list opener
)       2   parameter list closer

Test:
my ($i, $total);
my-for {$i=1; $total=0}, {$i <= 3}, {++$i}, {
    say $i;
    $total = $total + $i;
}
say "total: $total";

tcl, could I say 0 due to point 1.?
If the question was "how many ways your language allow you to do it", tcl would certainly score a good amount.

for

The language's normal for works this way; it should me noted that tcl has no keywords, so for works exactly like a function (side note: its behaviour can even be redefined!). Then, there is no need to implement it:
for {set i 0;set total 1} {$i<=3} {incr i} {puts $i; incr total $i}
puts total:\ $total

proc

Implement a function, strictly according to the question.
2.1. uplevel
The uplevel 1 will execute its contents 1 level up in the call stack, to allow there the access to the variables of the for input; otherwise we could not access $total, because it would be not defined.
proc F {s t i b} {uplevel 1 [list for $s $t $i $b]}
F {set i 0;set total 1} {$i<=3} {incr i} {puts $i; incr total $i}
puts total:\ $total

2.2. tailcall
From tailcall documentation: "The tailcall command replaces the currently executing procedure, lambda application, or method with another command."
proc P args {tailcall for {*}$args}
P {set i 0;set total 1} {$i<=3} {incr i} {puts $i; incr total $i}
puts total:\ $total

interp alias

You can say to one of the interpreters currently existing on interpreters tree that a command has an alias. I didn't create any interpreter, so I am interested on the tree's root interpreter, which path is an empty string, represented by {}. The following line means: "Create the alias R on the root interpreter, which will re-route calls to it to for on the root interpreter.
interp alias {} R {} for
R {set i 0;set total 1} {$i<=3} {incr i} {puts $i; incr total $i}
puts total:\ $total

set

You can define a var that will have the same value has for command:
set S for
$S {set i 0;set total 1} {$i<=3} {incr i} {puts $i; incr total $i}
puts total:\ $total

rename

You can change the name of the function. Note: From now on, you can not call for directly again! Now you must always call f, until you rename it back!
rename for f
f {set i 0;set total 1} {$i<=3} {incr i} {puts $i; incr total $i}
puts total:\ $total

demo

Almost every language has a "for" loop; giving the builtin one is definitely cheating.
uplevel is like eval and is worth 100 points!

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Quote-Safe Quines
Your task is simple: write a program (or function) that takes no input and outputs (or returns) its source code. The catch is that when the program is wrapped in "quotes" (Unicode character 34), it should again output its (now quoted) source code.
Standard rules for quines apply. This is code-golf, so the shortest program (in bytes) wins.

@ATaco think creatively. The code in quotes normally isn't executed, but when the entire program is surrounded with quotes those sections are executed.

Hmm, Good point.

This might work with BF on implementations that support !...

Must you use "? Some languages support two or three quote characters.

must the output include the quotes the second time through?

In my answer, I provided a 1 byte solution. But, I am unsure if it is considered cheating. By definition it satisfies everything I have read about Quines and what is asked in this question, but for some reason I do not feel right about it.

@tkellehe Meta: What counts as a proper quine? As far as I understand your 1-byte quine, it violates the code/data requirement formulated in the highest voted post.

@Laikoni, thank you! That makes more sense. I knew it didn't feel right:)

How does this challenge work in a language that works as follows: the program is written in a character set which contains quotes, and the interpreter detects it as such; however, if you add quotes around the program (in that character set), the interpreter treats the octets that make up those quotes as a character set selection directive, and reinterprets the whole file in a character set that doesn't contain quotes?

@ais523 If the unquoted quine was written in character set A, then prepending and appending bits representing quotes in character set A to the program should produce the desired behavior, even if the interpreter interprets it with a different character set.

Noodel, 9 7 bytes
This version works the same way as the other, just that I forgot that Noodel has a way to run a block of code once and I made the language...
Ḷ1ḥ-Ð1ḥ@€
ḷḥ-Ðḥ@ḅ

Try it:)

How it Works
ḷḥ-Ðḥ@ḅ # Single statement that builds itself as a string.
ḷ       # Loop the following block of code unconditionally.
 ḥ-     # Push the string literal of the token preceding this one which pushes "ḷ" onto the stack.
   Ð    # Push the stack as an array to stdout (since is an array it is done by reference).
    ḥ@  # Push the string literal for this block of code which pushes "ḥ-Ðḥ@ḅ" onto the stack.
      ḅ # Break out of the given loop. (The stack is now ["ḷ", "ḥ-Ðḥ@ḅ"]).

        # The top of the stack is popped off and displayed which modifies the array to produce {["ḷ"], "ḥ-Ðḥ@ḅ"} in stdout.

Quote-Safety
Placing the " character before and after the program works because Noodel has a set of of characters dedicated to what I call printables. These are immediately parsed as string literals when placed by themselves and allow for easily printing something to the screen. So unlike most languages, Noodel sees the normal ASCII set that is considered print worthy as direct string literals (except for space and line feed) therein quoting the code is merely seen as pushing on strings.
"ḷḥ-Ðḥ@ḅ"

"         # Pushes on the string literal "\"" onto the stack.

 ḷḥ-Ðḥ@ḅ  # Same execution as before, simply builds the Quine for this loop.
 ḷ        # Loop the following block of code unconditionally.
  ḥ-      # Push the string literal of the token preceding this one which pushes "ḷ" onto the stack.
    Ð     # Push the stack as an array to stdout (since is an array it is done by reference).
     ḥ@   # Push the string literal for this block of code which pushes "ḥ-Ðḥ@ḅ" onto the stack.
       ḅ  # Break out of the given loop. (The stack is now ["\"", "ḷ", "ḥ-Ðḥ@ḅ"]).

        " # Pushes on the string literal "\"" onto the stack.

          # The top of the stack is popped off and displayed which modifies the array to produce {["\"", "ḷ", "ḥ-Ðḥ@ḅ"], "\""} in stdout.

"Try it:)"

Snippets

I don't think using e is valid. The question doesn't ask for the character encoded as the byte 34, but for the Unicode character 34. No matter which encoding you use, there is only one: "

@Dennis, I am guessing what you are saying is the reference to the Unicode character 34 was just to ensure the everyone was using the same "? (Sorry, just trying to make sure I understand what you are saying) Also, should I remove all of the text in the answer referring to using e?

Yes, there are thousands of encodings, but only one Unicode character set. Since " works, I'd just remove the discussion and simply use ".

Python 2 3, 181 152 130 124 122 100 98 96 84 bytes
-12 bytes thanks to Jakque.
a=1;""";a=0;" """;p='"a=1;""";a=0;" """;p=%r;print(p[a:~a]%%p)#".';print(p[a:~a]%p)#

Try it online! The TIO comes with a header and footer that automatically test the validity of the quine. You can clear them to just run the quine.
This code works by (ab)using the triple-quoted strings and string literal concatenation in Python.

";b=""";b=" """; ignores ';b=' and sets b to ' '.
"";b=""";b=" """; ignores the empty string and sets b to ';b=" '.

The rest of the code then implements the traditional Python quine using %r string formatting, with some additional code that strips the extra quotes depending on b.
Older version from 2017, 122 bytes
""" """>" "or exec("oct=0");p='"""" """>" "or exec("oct=0");p=%r;a=oct==0;print(p[a:~a]%%p)#".';a=oct==0;print(p[a:~a]%p)#

Try it online!
""" """ is equal to ' ' and """" """ is equal to '" '.
The code does use exec, but not for the "non-quiney" way of executing data as code, just for setting a variable from inside an expression. The exec is properly encoded in the data, too.
The first statement compares the string, possibly with a quote prepended, to " ", and sets the variable oct accordingly. (The variable could've been any short builtin.) The final part then checks if oct is unchanged.
An alternative version using the "cheaty" exec comes in at 126 bytes with less repeated code:
""" """>" "and exec("oct=0");s='"""" """>" "and exec("oct=0");s=%r;p=%r;exec(p)#".';p='a=oct!=0;print(s[a:~a]%(s,p))';exec(p)#

Try it online!

Can you replace oct with id?

@pxeger Thanks for bringing me back to this post - in fact, I came up with a new strategy that saved 22 bytes instead of 4! :D

-12 bytes : You don't need the "; at the start of your code, it will only swap the values of b beetween the quoted quine and the unquoted quine but it is just a matter of changing the comparison in a. Also, why don't you directly declare a intead of b at the start? : Try it online!

StandardML, 182 176 108 bytes
";str(chr 34)^it;(print(it^it);fn x=>print(x^it^x^it))";str(chr 34)^it;(print(it^it);fn x=>print(x^it^x^it))

Unquoted version: Try it on codingground.
Quoted version: Try it on codingground.
Note that the output looks something like this
> val it = "{some string}" : string
> val it = "{some string}" : string
{output to stdout}> val it = fn : string -> unit

because the code is interpreted declaration by declaration (each ; ends a declaration) and shows the value and type of each declaration.

Background
In SML there is a quine of the form "":
str(chr 34);(fn x=>print(x^it^x^it))"str(chr 34);(fn x=>print(x^it^x^it))"

and one in the form "":
";str(chr 34)^it;print(it^it)";str(chr 34)^it;print(it^it)

Both rely on the fact that the -part contains no quotes and can thus be quoted with out the need for escaping anything, the " needed to output the quine are given by str(chr 34).
They also heavily rely on the implicit identifier it which is used when no explicit identifier is given in a declaration.
In the first quine str(chr 34); binds it to the string containing ", fn x=> starts an anonymous function taking one argument x, then concatenates x^it^x^it and prints the resulting string. This anonymous function is directly applied to a string containing the program code, so the concatenation x^it^x^it yields "".
The second quine starts with just the program code as string ";str(chr 34)^it;print(it^it)"; which is bound to it. Then str(chr 34)^it; concatenates a quote to the start of the string and as again no explicit identifier is given, the resulting string " is bound to it. Finally print(it^it) concatenates the string with itself yielding "" which is then printed.

Explanation
Edit: No longer up to date with the 108-byte version, however one might understand it too after reading this explanation.
The quote-safe quine combines both of the above approaches and is itself of the form "". Putting this in again in quotes yields """", so we get an empty string and then a quine of the other form.
That means the program is either given its own source in the form " by the identifier it, or it is just " and we are given our own source  as argument and must thus be a function which handles such an argument.
(if size it>1then(print(it^it);fn _=>())else fn x=>print(it^it^x^it^x^it))

To identify in which case we are, we check whether the size of it is larger than 1. If not then it is " and we are in the second case, so the else-part returns an anonymous function fn x=>print(it^it^x^it^x^it) which is then called because its followed by source as string. Note the leading it^it^ which is needed for the empty string at the start of the of the program.
If size it is larger than 1 we are in the then-part and just perform print(it^it), right? Not quite, because I neglected to tell you that SML is strongly typed which means that a conditional if <cond> then <exp_1> else <exp_2> must always have the same type which again means that the expressions <exp_1> and <exp_2> need to have the same type. We already know the type of the else part: An anonymous function which takes a string and then calls print has type string -> <return type of print>, and print has type string -> unit (unit is in some way similar to void in other languages), so the resulting type is again string -> unit.
So if the then part was just print(it^it) which has type unit, we would get a type mismatch error. So how about fn _=>print(it^it)? (_ is a wildcard for an argument that is not used) This anonymous function on its own has type 'a -> unit where 'a stands for an arbitrary type, so in the context of our conditional which enforces a string -> unit type this would work. (The type variable 'a gets instantiated with type string.) However, in this case we would not print anything as the anonymous function is never called! Remember, when we go in the then-part the overall code is "", so the -part evaluates to a function but, as nothing comes after it, its not called.
Instead we use a sequentialisation which has the form (<exp_1>; ...; <exp_n>) where <exp_1> to <exp_n-1> may have arbitrary types and the type of <exp_n> provides the type of the whole sequentialisation. From a functional point of view the values of <exp_1> to <exp_n-1> are simply discarded, however SML also supports imperative constructs so the expressions may have side effects. In short, we take (print(it^it);print) as the then-part, thus printing first and then returning the function print which has the correct type.

V, 27, 23 bytes
éPñi"éP241"qpá"lxx|xÿ

Try it online!
Since this contains some unprintable characters, here is a readable version:
éPñi"éP<C-v>241<esc>"qpá"lxx|xÿ

and here is a hexdump:
00000000: e950 f169 22e9 5016 3234 311b 2271 70e1  .P.i".P.241."qp.
00000010: 226c 7878 7c78 ff                        "lxx|x.

So the very first thing we need to do is to determine if the first character is a quote. éP inserts a 'P' character, but "éP is a NOOP. After that, we run a slight modification on the standard extendable quine, which is:
ñi<C-v>241<esc>"qpÿ

We're going to do it slightly differently though. First off we need to insert the starting "éP" text. So we do
ñ                        " Start recording into register 'q'
 i                       " Enter insert mode
  "éP<C-v>241<esc>       " Enter the following text: '"éPñ'
                  "qp    " Paste the text in register 'q'
                     á"  " Append a '"'

Here is where the branching happens. The text currently in the buffer is
"éPñi"éP<C-v>241<esc>"qpá"P
Cursor is here ----------^

Unless we wrapped it in quotes, in that case the 'P' would never have been inserted, and the buffer is:
"éPñi"éP<C-v>241<esc>"qpá"
Cursor is here ----------^

Since we are still recording, we can do whatever we want here, and it will get added to the buffer when the "qp happens. So from here it's pretty easy to conditionally delete the quotes:
l           " Move one character to the right. If there is no character to the right,
            " then this is effectively a "break" statement, stopping playback of the recording
 xx         " Delete two characters (the '"P')
   |        " Move to the first character on this line
    x       " Delete one character
     ÿ      " End the program

JavaScript (ES6), 239 237 bytes
Set=``;eval(";a='Set=``;eval(~;a=1;S=String.fromCharCode;q=S(34);r=Set&&q;s=S(39);alert(r+a.replace(/[^ -}]/g,q).replace(1,s+a+s)+r);~)';S=String.fromCharCode;q=S(34);r=Set&&q;s=S(39);alert(r+a.replace(/[^ -}]/g,q).replace(1,s+a+s)+r);")

Take care to try each version in a fresh environment (e.g., a new browser tab)
There has got to be at least one way to simplify this...

I suppose you could use an array for the replaces like so: [x="replace"]. Might break things though, I'm not very experienced with quines...

Vyxal D, 29 bytes
`Dqp^≈[_\\"pǏ]₴`Dqp^≈[_\"pǏ]₴

Try it Online!
Explained:
`...`Dqp^≈[_\"pǏ]₴
`...`                 Push half the source code
     D                Make 3 copies of the source code
      qp              Uneval the first copy (quote, escape) and prepend it to the second
        ^             Reverse the stack
         ≈[_\"pǏ]     Execute if all elements are the same.
                      Since this is not the case, it just pops the third copy of the source code
                 ₴    Print the source

Quoted version: ("Try it Online!")
"`...`Dqp^≈[_\"pǏ]₴"
"                       Push the set [0, 0]
 `...`                  Push the source code
      D                 Make 3 copies of the source code
       qp               Uneval the first copy and prepend it to the second
         ^              Reverse the stack, putting [0, 0] on the top
          ≈[     ]      Execute if all elements of the top of the stack are the same.
                        This is the case because of the [0, 0] pushed by "
            _           Remove the third copy of the source from the stack
             \"         Push `"`
               pǏ       Prepend and enclose the source with `"`
                  ₴     Print the source
                   "    Push [0, 0], having no effect because the source is already printed

Perl 5, 59 bytes
";$\=q;";;$_=q(print$\,'";$\=q;";;$_=q('."$_);eval#");eval#

Try it online!
Quoted
"";$\=q;";;$_=q(print$\,'";$\=q;";;$_=q('."$_);eval#");eval#"

Try it online!
Explanation
In the original, there is an unused string ";$\=q;" separated by ;; before the standard quine body which first prints $\ (which is empty by default) followed by the unused string and the body followed by #.
In the quoted string, there is an unused string "", separated by ; then $\ is set to q;"; which is Perl's custom quotes q;...; wrapping the double-quote char. Then the quine body is built and $\ is automatically printed after all content adding the final " in the quoted string.

Python 2, 68 bytes & Python 3, 70 bytes
Python 2, 68 bytes:
x=""#";x='"'
s='x=""#";x=\'"\'\ns=%r;print x+s%%s+x#';print x+s%s+x#

Try it online!
Python 3, 70 bytes:
x=""#";x='"'
s='x=""#";x=\'"\'\ns=%r;print(x+s%%s+x)#';print(x+s%s+x)#

Try it online!
How does it work? :

Without quotes: x=""#";x='"' will stop the execution at the coment # char => x=""
With quotes: "x=""#";x='"' have just 2 string concatened "x=" and "#" which don't do anything, and an assignation : x='"'

Now x is filled with the good char (quote or empty).
We use then the standard python quine : s='s=%r;print(s%%s)';print(s%s) adding a few extras to make it work here, for example # at the end to avoid an EOF Error when a " is added at the end of the program
Then, we just print our quine adding x at the start and at the end of the string

Haskell, 142 bytes
--"#p=p['"']>>"--\""#p
k#p=p x>>print x>>p k;main="--"#putStr;x="--\"#p=p['\"']>>\"--\\\"\"#p\nk#p=p x>>print x>>p k;main=\"--\"#putStr;x="
--

Try it online!
"--"#p=p['"']>>"--\""#p
k#p=p x>>print x>>p k;main="--"#putStr;x="--\"#p=p['\"']>>\"--\\\"\"#p\nk#p=p x>>print x>>p k;main=\"--\"#putStr;x="
--"

Try it online!
This uses a pretty simple detection method.
The first line is normally a comment.
--"#p=p['"']>>"--\""#p

However when a quote is added to the front
"--"#p=p['"']>>"--\""#p

It becomes the declaration of an operator (#).  So what this program does is defines (#) such that it prints the normal source for when called with "--"#putStr, however when the quotes appear the new definition supersedes it and prints the source with quotes.

Vyxal D, 18 17 bytes
Normal
`q‛:Ė+$[‛""$j,`:Ė

Try it Online!
Quoted
"`q‛:Ė+$[‛""$j,`:Ė"

Try it Online!
Explanation :
# Normal

`q‛:Ė+        `   # structure for a quine  => [ <quine> ]
               :Ė # add a copy of the structure on the stack and exec it
 q                # push the quoted string on the stack => [ `<quine>` ]
  ‛:Ė+            # add ':Ė' to the string on the stack => [ `<quine>`:Ė ]
      $           # swap the two values on top of he stack => [ `<quine>`:Ė , 0 ]
       [          # pop and check if it is nul (it is) => [ `<quine>`:Ė ]
        ‛""$j,    # irrevelent here
                  # implicit output

# Quoted

"                 # listify the two elements on top of the stack => [ [0,0] ]
`q‛:Ė+        `   # structure for a quine  => [ [0,0] , <quine> ]
               :Ė # add a copy of the structure on the stack and exec it
 q                # push the quoted string on the stack => [ [0,0] , `<quine>` ]
  ‛:Ė+            # add ':Ė' to the string on the stack => [ [0,0] , `<quine>`:Ė ]
      $           # swap the two values on top of he stack => [ `<quine>`:Ė , [0,0] ]
       [          # pop and check if it is nul (it is not as it's a list) => [ `<quine>`:Ė ]
        ‛""       # add `""` to the stack => [ `<quine>`:Ė, `""` ]
           $j     # swap the two elements and join => [ "`<quine>`:Ė" ]
             ,    # print => []
                " # listify the two elements on top of the stack => [ [0,0] ]
                  # no implicit output as it has already printed via ,

Zsh, 76 bytes
: "||z=\" #"
s=': "||z=\" #"
s=\47%s\47
printf $z$s$z $s
'
printf $z$s$z $s

Try it online!
"Try it online!"
Note the trailing newline.
Without the quotes, the first line is a call to the built-in no-op :, which ignores its string argument ||z=" #. The variable z remains empty.
With quotes, the first line is:

": ": execute :  (note the space), which is a non-existent command
||: if this fails (which it will, since :  doesn't exist), then:
z=\": set the variable z to a single double-quote "
 #": comment; ignored

The extra " on the last line is unmatched, but zsh helpfully ignores that until after the program has executed because it's a separate command line.
The rest is a pretty standard shell quine, but we surround the string with $z so it gets double quotes if necessary.


text:
The beautiful pattern drawer (Little cubes included)
The beautiful pattern drawer
Good morning PPCG !
The other day, when I was trying to help someone on Stack Overflow, a part of his problem gave me an idea for this challenge.
First of all, check the following shape :

Where all black numbers are the index of the points in the shape and all dark-blue numbers are the index of the links between the points.
Now, given an hexadecimal number for 0x00000 to 0xFFFFF, you need to draw a shape in the console using only character space and "■" (using the character "o" is okay too).
Here are some examples where hexadecimal number is input and shape is output :
0xE0C25 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■               ■
■               ■
■               ■
■ ■ ■ ■ ■       ■
        ■       ■
        ■       ■
        ■       ■
        ■ ■ ■ ■ ■
0xC1043 :
■ ■ ■ ■ ■ ■ ■ ■ ■
              ■
            ■
          ■
        ■
      ■
    ■
  ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xE4F27 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■       ■       ■
■       ■       ■
■       ■       ■
■ ■ ■ ■ ■ ■ ■ ■ ■
■       ■       ■
■       ■       ■
■       ■       ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xF1957 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■           ■ ■
■   ■       ■   ■
■     ■   ■     ■
■       ■       ■
■     ■   ■     ■
■   ■       ■   ■
■ ■           ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xD0C67 :
■ ■ ■ ■ ■ ■ ■ ■ ■
  ■             ■
    ■           ■
      ■         ■
■ ■ ■ ■ ■       ■
      ■ ■       ■
    ■   ■       ■
  ■     ■       ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0x95E30 :
■ ■ ■ ■ ■       ■
  ■     ■     ■ ■
    ■   ■   ■   ■
      ■ ■ ■     ■
■ ■ ■ ■ ■ ■ ■ ■ ■
        ■ ■
        ■   ■
        ■     ■
        ■       ■
0x95622 :
■ ■ ■ ■ ■       ■
  ■     ■     ■
    ■   ■   ■
      ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
        ■
        ■
        ■
■ ■ ■ ■ ■
0xC5463 :
■ ■ ■ ■ ■ ■ ■ ■ ■
        ■     ■
        ■   ■
        ■ ■
■ ■ ■ ■ ■
      ■ ■
    ■   ■
  ■     ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xE5975 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■       ■     ■ ■
■       ■   ■   ■
■       ■ ■     ■
■       ■       ■
■     ■ ■ ■     ■
■   ■   ■   ■   ■
■ ■     ■     ■ ■
■       ■ ■ ■ ■ ■
0xB5E75 :
■ ■ ■ ■ ■       ■
■ ■     ■     ■ ■
■   ■   ■   ■   ■
■     ■ ■ ■     ■
■ ■ ■ ■ ■ ■ ■ ■ ■
      ■ ■ ■     ■
    ■   ■   ■   ■
  ■     ■     ■ ■
■       ■ ■ ■ ■ ■
0xF4C75 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■     ■       ■
■   ■   ■       ■
■     ■ ■       ■
■ ■ ■ ■ ■       ■
      ■ ■ ■     ■
    ■   ■   ■   ■
  ■     ■     ■ ■
■       ■ ■ ■ ■ ■
0xF5D75 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■     ■     ■ ■
■   ■   ■   ■   ■
■     ■ ■ ■     ■
■ ■ ■ ■ ■       ■
■     ■ ■ ■     ■
■   ■   ■   ■   ■
■ ■     ■     ■ ■
■       ■ ■ ■ ■ ■

Here are some explanation about how it works :
0xFFFFF(16) = 1111 1111 1111 1111 1111(2)

You here have 20 bits, each bit says whether a link exists or not.
Index of the Most Significant Bit (MSB) is 0 (picture reference) or the Less Significant Bit (LSB) is 19 (picture reference again).
Here's how it works for the first shape given as example :
0xE0C25(16) = 1110 0000 1100 0010 0101(2)

Meaning you'll have the following existing links : 0,1,2,8,9,14,17,19.
If you highlight the lines on the reference picture with those numbers, it will give you this shape :
■ ■ ■ ■ ■ ■ ■ ■ ■
■               ■
■               ■
■               ■
■ ■ ■ ■ ■       ■
        ■       ■
        ■       ■
        ■       ■
        ■ ■ ■ ■ ■

Here is a simple and ungolfed Python implementation if you need more help :
patterns = [
  0xE0C25, 0xC1043, 0xE4F27, 0xF1957,
  0xD0C67, 0x95E30, 0x95622, 0xC5463,
  0xE5975, 0xB5E75, 0xF4C75, 0xF5D75
]

def printIfTrue(condition, text = "■ "):
  if condition:
    print(text, end="")
  else:
    print(" "*len(text), end="")

def orOnList(cube, indexes):
  return (sum([cube[i] for i in indexes]) > 0)

def printPattern(pattern):
  cube = [True if n == "1" else False for n in str(bin(pattern))[2::]]
  for y in range(9):
    if y == 0: printIfTrue(orOnList(cube, [0, 2, 3]))
    if y == 4: printIfTrue(orOnList(cube, [2, 4, 9, 11, 12]))
    if y == 8: printIfTrue(orOnList(cube, [11, 13, 18]))
    if y in [0, 4, 8]:
      printIfTrue(cube[int((y / 4) + (y * 2))], "■ ■ ■ ")
      if y == 0: printIfTrue(orOnList(cube, [0, 1, 4, 5, 6]))
      if y == 4: printIfTrue(orOnList(cube, [3, 5, 7, 9, 10, 13, 14, 15]))
      if y == 8: printIfTrue(orOnList(cube, [12, 14, 16, 18, 19]))
      printIfTrue(cube[int((y / 4) + (y * 2)) + 1], "■ ■ ■ ")
    elif y in [1, 5]:
      for i in range(7):
        if i in [2, 5]:
          print(" ", end=" ")
        printIfTrue(cube[y * 2 + (1 - (y % 5)) + i])
    elif y in [2, 6]:
      for i in range(5):
        if i in [1, 2, 3, 4]:
          print(" ", end=" ")
        if i in [1, 3]:
          if i == 1 and y == 2:
            printIfTrue(orOnList(cube, [3, 4]))
          elif i == 3 and y == 2:
            printIfTrue(orOnList(cube, [6, 7]))
          if i == 1 and y == 6:
            printIfTrue(orOnList(cube, [12, 13]))
          elif i == 3 and y == 6:
            printIfTrue(orOnList(cube, [15, 16]))
        else:
          printIfTrue(cube[(y * 2 - (1 if y == 6 else 2)) + i + int(i / 4 * 2)])
    elif y in [3, 7]:
      for i in range(7):
        if i in [2, 5]:
          print("  ", end="")
        ri, swap = (y * 2 - 2) + (1 - (y % 5)) + i, [[3, 6, 12, 15], [4, 7, 13, 16]]
        if ri in swap[0]: ri = swap[1][swap[0].index(ri)]
        elif ri in swap[1]: ri = swap[0][swap[1].index(ri)]
        printIfTrue(cube[ri])
    if y == 0: printIfTrue(orOnList(cube, [1, 7, 8]))
    if y == 4: printIfTrue(orOnList(cube, [6, 8, 10, 16, 17]))
    if y == 8: printIfTrue(orOnList(cube, [15, 17, 19]))
    print()

for pattern in patterns:
  printPattern(pattern)

Of course it's not perfect and it's pretty long for what it should do, and that's the exact reason why you're here !
Making this program ridiculously short :)
This is code-golf, so shortest answer wins !

Can we print a single trailing space on lines? Your examples contain them.

Yup :) It's allowed

Is graphical output allowed?

Is a leading space allowed as well?

Does it have to be a function, or can we get input directly from the user?

Do you require hexadecimal input or is decimal ok?

Maybe all the code golf is just getting to me, but that code is painful to read…

@12Me21 You can get input from user !

@12Me21 Graphical output is not allowed as you can use some stuff like "drawline" and not have to care abour corners overlapping :)

@Arnauld Leading space is allowed, doesn't change much here :)

@Titus Hexadecimal required !

JavaScript (ES6), 202 188 187 bytes

let f =

n=>`0${x=',16,-54,21,-26,21,21,-26,21,166'}${x},16`.split`,`.map((d,i)=>(k-=d,n)>>i&1&&[..."ooooo"].map(c=>g[p-=(k&3||9)^8]=c,p=k>>2),g=[...(' '.repeat(9)+`
`).repeat(9)],k=356)&&g.join``

console.log(f(0xE0C25))
console.log(f(0xC1043))
console.log(f(0xE4F27))
console.log(f(0xF1957))

How it works
n =>                                                 // given 'n':
  `0${x = ',16,-54,21,-26,21,21,-26,21,166'}${x},16` // build the list of delta values
  .split`,`.map((d, i) =>                            // split the list and iterate
    (k -= d, n) >> i & 1 &&                          // update 'k', test the i-th bit of 'n'
    [..."ooooo"].map(c =>                            // if the bit is set, iterate 5 times:
      g[                                             //
        p -= (k & 3 || 9) ^ 8                        // compute the direction and update 'p'
      ] = c,                                         // write a 'o' at this position
      p = k >> 2                                     // initial value of 'p'
    ),                                               //
    g = [...(' '.repeat(9) + `\n`).repeat(9)],       // initialization of the 'g' array
    k = 356                                          // initial value of 'k'
  )                                                  //
  && g.join``                                        // yield the final string

We work on a grid g of 9 rows of 10 characters. The grid is initially filled with spaces, with a LineFeed every 10th character.
Each segment is defined by a starting position and a direction.
Directions are encoded as follow:
ID | Dir.| Offset
---|-----|-------
 0 |  W  |  -1        Offset encoding formula:
 1 | NE  |  -9        -((ID || 9) ^ 8)
 2 |  N  |  -10
 3 | NW  |  -11

Each segment is encoded as an integer:

the direction is stored in bits #0 and #1
the starting position is stored in bits #2 to #8

For instance, segment #3 starts at position 55 and uses the 3rd direction. Therefore, it's encoded as (55 << 2) | 3 == 223.
Below is the resulting list of integers, from segment #19 to segment #0:
356,340,394,373,399,378,357,383,362,196,180,234,213,239,218,197,223,202,36,20

Once delta-encoded, starting at 356, it becomes:
0,16,-54,21,-26,21,21,-26,21,166,16,-54,21,-26,21,21,-26,21,166,16

Which is finally encoded as:
`0${x=',16,-54,21,-26,21,21,-26,21,166'}${x},16`

Oops... Forgot the spaces in between. Fixing that.

Python 3, 289 bytes
def f(n):
 for r in range(9):print(*(" o"[any(n&1<<ord(c)-97for c in"trq|t|t|t|tspon|s|s|s|sml|r|q||p|o|n||m|l|r||qp||o||nm||l|r|p||q|o|m||n|l|rpkih|k|k|k|qomkjgfe|j|j|j|nljdc|i|h||g|f|e||d|c|i||hg||f||ed||c|i|g||h|f|d||e|c|igb|b|b|b|hfdba|a|a|a|eca".split("|")[r*9+c])]for c in range(9)))

Nothing smart, just hardcoding.

Couldn't "trq|t...a|eca".split("|") become "tqr t...a eca".split()?

@Loovjo Nope, .split() destroys ||.

Ruby, 116 bytes
->n{s=[' '*17]*9*$/
20.times{|i|j=i%9
n>>19-i&1>0&&5.times{|k|s[i/9*72+(j>1?~-j/3*8+k*18:j*16)+k*(2--j%3*2)]=?O}}
s}

This relies on a couple of patterns I observed. Firstly, the pattern repeats every 9 lines. Secondly, if the start points of the horizontal lines are chosen appropriately, the x directions cycle continuously through right, left, straight.
Ungolfed in test program
f=->n{
   s=[' '*17]*9*$/                    #Setup a string of 9 newline separated lines of 17 spaces.
   20.times{|i|                       #For each of the 20 bits..
     j=i%9                            #The pattern repeats every 9 bits.
     n>>19-i&1>0&&                    #If the relevant bit is set,
     5.times{|k|                      #draw each of the 5 points on the relevant line.
       s[i/9*72+                      #There are 9 lines starting on each row. Row y=0 starts at 0 in the string, row y=1 at 72, etc.
       (j>1?~-j/3*8+k*18:j*16)+       #~-j=j-1. For j=2..8, the starting x coordinates are (0,0,1,1,1,2,2)*8. For j=0 and 1 starting x coordinates are 0 and 16.
       k*(2--j%3*2)                   #From the starting points, draw the lines right,left,straight. Down movement if applicable is given by conditional k*18 above.
       ]=?O                           #Having described the correct index to modify, overwrite it with a O character.
     }
   }
s}                                    #Return the string.

[0xE0C25, 0xC1043, 0xE4F27, 0xF1957,
  0xD0C67, 0x95E30, 0x95622, 0xC5463,
  0xE5975, 0xB5E75, 0xF4C75, 0xF5D75].map{|m|puts f[m],'---------'}

I believe there is a 112 byte solution using a 20-character string and some decoding to define the parameters of the 20 lines. I will try this later if I have time.

Nice explanation !

PHP, 142 150 149 bytes
for($r="";$c=ord(",(NMKJIGFHDjigfecbd`"[$i]);)if(hexdec($argv[1])>>$i++&1)for($p=96^$c&~$k=3;$k++<8;$p+=7+($c&3?:-6))$r[$p]=o;echo chunk_split($r,9);

prints the shape as far as needed; i.e. if the lower part is empty, it will be cut.
Run with php -nr '<code>' <input>. Do not prefix input
Test it online
Add 11 bytes for no cutting: Insert ,$r[80]=" " after $r="".
encoding explained
Every line can be described with a starting point and one of four directions.
Drawing on a 9x9 grid, the starting position ranges from 0,0 to 8,4; or, combined, from 0 to 8*9+4=76. Luckily, all starting points [0,4,8,36,40,44,72,76] are divisible by 4; so the direction code [0..3] can be squeezed into bits 0 and 1 -> no shifting needed at all.
For an easy calculation of the cursor movement, 0 is taken for east (only direction with no vertical movement) and [1,2,3] for south-west, south, south-east, where the offset is 9 (for vertical movement) plus [-1,0,1] -> [8,9,10] -> delta=code?code+7:1.
The direction for the first and last lines being east, that results in codes ranging from 0 to 76 [0+0,4+0,0+2,0+3,4+1,4+2,4+3,8+1,8+2,...,44+1,44+2,72+0,76+0]; and bitwise xor 96 on each value results in printable and unproblematic ascii codes [96,100,98,99,101,102,103,105,106,68, 72,70,71,73,74,75,77,78,40,44] ->  `dbcefgijDHFGIJKMN(,. The code uses the LSB for bit 0, while line 0 corresponds to the MSB, so the string has to be reversed. Finito.
breakdown
for($r="";                  // init result string, loop through line codes
    $c=ord(",(NMKJIGFHDjigfecbd`"[$i]);)
    if(hexdec($argv[1])>>$i++&1)// if bit $i is set, draw line 19-$i:
        for($p=96^$c&~$k=3          // init $k to 3, init cursor to value&~3
            ;$k++<8;                // loop 5 times
            $p+=7+($c&3?:-6)            // 2. map [0,1,2,3] to [1,8,9,10], move cursor
        )
            $r[$p]=o;                   // 1. plot
echo chunk_split($r,9);     // insert a linebreak every 9 characters, print

some golfing explained

Since ^96 has no effect on the lower two bits, it can be ignored when extracting the direction; so there is no need to store the value in a variable, which saves 5 bytes on the cursor init.
Using ~3 instead of 124 saves one byte and allows the next golfing:
Initializing the looping counter $k=3 inside the $p assignment saves two bytes
and it doesn´t hurt the pre-condition (since the upper value still has one digit).
Using a string for the result has the shortest initialization and plotting possible: When a character is set beyond the end of a string, PHP implicitly sets the missing characters to space. And chunk_split is the shortest way to insert the linebreaks.
I don´t even want to know how much more anything else would take.
7+($c&3?:-6) is one byte shorter than $c&3?$c%4+7:1.
Added hexdec() (8 bytes) to satisfy the input restriction.

JavaScript, 184 183 178 168 167 bytes

f=
n=>[...`<>K[LM]NO\\^k{lm}no|~`].map((e,i)=>n>>i&1&&[0,2,4,6,8].map(i=>a[(e&102)*4+(e&17||15)*i]=`o`,e=~e.charCodeAt()),a=[...(` `.repeat(31)+`
`).repeat(9)])&&a.join``
<input oninput=o.textContent=f(+this.value)><pre id=o>

Was originally 206 bytes but @Arnauld's answer inspired me to investigate a one-dimensional array solution. Edit: Saved 1 byte thanks to @edc65. Saved 5 15 bytes thanks to @Arnauld. Saved a further byte by tweaking the choice of characters.

[0,1,2,3,4] is shorter

I think you can save 4 bytes by using [67,65,52,36,51,50,34,49,48,35,33,20,4,19,18,2,17,16,3,1] and [0,2,4,6,8].map(i=>a[(e&102)*4+(e&17||15)*i]='o')

Or you can use [..."ecVFUTDSREC6&54$32%#"] and [0,2,4,6,8].map(i=>a[(e&102)*4+(e&17||15)*i]='o',e=e.charCodeAt()-34) to save 10 more bytes.

@Arnauld You seem to have undercounted your saving by 1, and I also managed to golf off an extra byte by using ~ instead of -34 (sadly I fall foul of \\ which is why I don't save 2 bytes).

I wonder if you could replace this '' with ASCII character #220.

Batch, 491 bytes
@set n=%1
@for %%i in ("720896 524288 524288 524288 843776 262144 262144 262144 268288" "131072 65536 0 32768 16384 8192 0 4096 2048" "131072 0 98304 0 16384 0 12288 0 2048" "131072 32768 0 65536 16384 4096 0 8192 2048" "165248 1024 1024 1024 89312 512 512 512 10764" "256 128 0 64 32 16 0 8 4" "256 0 192 0 32 0 24 0 4" "256 64 0 128 32 8 0 16 4" "322 2 2 2 171 1 1 1 17")do @set s=&(for %%j in (%%~i)do @set/am=%1^&%%j&call:c)&call echo(%%s%%
:c
@if %m%==0 (set s=%s%  )else set s=%s%o

Note: The last line ends with a space. Putting an if conditional with a variable inside a for loop is beyond batch so that needs its own subroutine. Since it does nothing visible I fall through into it to exit. The ~ unquotes the strings in the outer loop allowing the inner loop to loop over the numbers. The numbers are simply the bitmasks for all the places where os should be drawn.

C, 267 262 260 256 characters
Counting escapes as 1 character
void f(int i){char*k="\0\x1\x2\x3\x4\x4\x5\x6\x7\x8\0\x9\x12\x1b\x24\0\xa\x14\x1e\x28\x4\xc\x14\x1c\x2d\x4\xd\x16\x1f\x28\x4\xe\x18\x22\x2c\x8\x10\x18\x20\x28\x8\x11\x1a\x23\x2c\x24\x25\x26\x27\x28\x28\x29\x2a\x2b\x2c\x24\x2d\x36\x3f\x48\x24\x2e\x38\x42\x4c\x28\x30\x38\x40\x48\x28\x31\x3a\x43\x4c\x28\x31\x3a\x43\x4c\x28\x32\x3c\x46\x50\x2c\x35\x3e\x47\x50\x48\x49\x4a\x4b\x4c\x4c\x4d\x4e\x4f\x50";for(int n=0,s,l;n<81;!(++n%9)&&putchar(10))for(s=l=0;s<20;!(++l%5||++s^20)&&putchar(32))if(i<<s&1<<19&&k[l]==n&&putchar(111))break;}

k is a lookup referring to which boxes to put an 'o' in.
Try it online!

Befunge, 468 bytes
~:85+`!#v_86*-:9`7*-48*%\82**+
3%2:/2\<$v0%2:/2\*g02*!g03%2:/2\*!+4g07%2:/2\*g02*!-8g06%2:/2\*g02*!-4g0
g!*20g*^00>50g*\2/:2%00g8-!*40g*\2/:2%30g8-!*20g*\2/:2%60g66+-!*\2/:2%70
`\5:p00:<g^*!-8g00%2:\-10:\p07-g00:p06+g00:p05`3:p04`\5:p03:<0\p02`3:p01
#o 8`#@_^4>*50g*\2/2%00g!*40g*0\>:#<1#\+_$!1+4g,48*,\1+:8`!#^_55+,$\1+:
g03%2:/2<-^!g00%2:/2\*g01*!g03%2:/2\*g01*!g07%2:/2\*!-4g06%2:/2\*g01*!-4
70g4-!*\^>!*50g*\2/:2%00g4-!*40g*\2/:2%30g8-!*10g*\2/:2%60g8-!*10g*\2/:2%

Try it online!
The first line reads a string from stdin, evaluating it as a hexadecimal number. The rest of the code is essentially just a double loop over the x/y coordinates of the grid, with a massive boolean calculation determining whether an o should be output for each location.
There's basically a separate condition for each of the 20 grid points, for example (the first four):
(y==0) * (x<5) * bit0
(y==0) * (x>3) * bit1
(x==0) * (y<5) * bit2
(x==y) * (y<5) * bit3

And then once we've calculated all 20 of them, we OR the lot together, and if that result is true, we output a o, otherwise we output a space.
Befunge doesn't have anything in the way of bit manipulation operations, so to extract the bits from the input, we're just repeatedly evalating n%2 and then n/=2 as we make our way through the 20 condition calculations.


text:
Which Day of Christmas is it?
Preface
In the well known carol, The Twelve Days of Christmas, the narrator is presented with several gifts each day. The song is cumulative - in each verse, a new gift is added, with a quantity one higher than the gift before it. One Partridge, Two Turtle Doves, Three French Hens, and so on.
At any given verse, N, we can calculate the cumulative sum of presents so far in the song by finding the Nth tetrahedral number, which gives the results:
Verse 1: 1
Verse 2: 4
Verse 3: 10
Verse 4: 20
Verse 5: 35
Verse 6: 56
Verse 7: 84
Verse 8: 120
Verse 9: 165
Verse 10: 220
Verse 11: 286
Verse 12: 364

For example, after verse 4, we've had 4*(1 partridge), 3*(2 turtle doves), 2*(3 French hens) and 1*(4 calling birds). By summing these, we get 4(1) + 3(2) + 2(3) + 1(4) = 20.
The Challenge
Your task is to write a program or function which, given a positive integer representing the number of presents 364 ≥ p ≥ 1, determines which day (verse) of Christmas it is.
For example, if p = 286, we are on the 11th day of Christmas. However, if p = 287, then the next load of presents has begun, meaning it is the 12th day.
Mathematically, this is finding the next tetrahedral number, and returning its position in the whole sequence of tetrahedral numbers.
Rules:

This is code-golf, so the shortest solution (in bytes) wins.
Standard golfing loopholes apply.
When it comes to days, your program must be 1-indexed.
Your submission must be a full program or a function - but not a snippet.

Test Cases
1   ->  1
5   ->  3
75  ->  7
100 ->  8
220 ->  10
221 ->  11
364 ->  12

Just in case it helps anyone, the n'th tetrahedral number is also the sum of the first n triangular numbers.

This might help: x=>{while(x>p)p+=r+=++i;return i}, I'm sure it can be made shorter in a language like JavaScript.

This is the earliest Christmas challenge ever, right? :)

Jelly, 7 6 bytes
-1 byte thanks to Dennis (use vectorised minimum, «, and first index, i)
R+\⁺«i

TryItOnline
How?
Not all that efficient - calculates the 1st through to nth tetrahedral numbers in order in a list and returns the 1-based index of the first that is equal to or greater.
R+\⁺«i - main link: n
R      - range                          [1,2,3,4,...,n]
 +\    - cumulative reduce by addition  [1,3,6,10,...,sum([1,2,3,4,...n])] i.e. triangle numbers
   ⁺   - duplicate previous link - another cumulative reduce by addition
                                        [1,4,10,20,...,nth tetrahedral]
    «  - min(that, n)                   [1,4,10,20,...,n,n,n]
     i - first index of n (e.g. if n=12:[1,4,10,12,12,12,12,12,12,12,12,12] -> 4)

Previous 7 byters using lowered range [0,1,2,3,...,n-1] and counting tetrahedrals less than n:
Ḷ+\⁺<µS,
Ḷ+\⁺<ḅ1,
Ḷ+\⁺<ċ1, and
Ḷ+\⁺<¹S

Python, 27 bytes
lambda n:int((n*6)**.33359)

Try it online!
A direct formula with some curve-fitting, same as the original one found by Level River St.
The shifted equation i**3-i==n*6 is close to i**3==n*6 for large i. It solves to i=(n*6)**(1/3). Taking the floor the rounds down as needed, compensating for the off-by-one.
But, there are 6 inputs on boundaries where the error takes it below an integer it should be above. All of these can be fixed by slightly increasing the exponent without introducing further errors.

Python, 38 bytes
f=lambda n,i=1:i**3-i<n*6and-~f(n,i+1)

The formula n=i*(i+1)*(i+2)/6 for tetrahedral numbers can be more nicely written in i+1 as n*6=(i+1)**3-(i+1). So, we find the lowest i for which i**3-i<n*6. Each time we increment i starting from 1, the recursive calls adds 1 to the output. Starting from i=1 rather than i=0 compensates for the shift.

Nice. I thought about golfing mine this way, but I didn't do it. Nevertheless, I'll try shifting; our answers will still be different.

Woah. Your new one is amazing.

The 26-byte version fails for 364, which is excluded from the test range. **.33359 works for one extra byte.

@Dennis Thanks. Python exclusive ranges strike again!

lambda n:n**.3336//.5501 saves a few bytes.

@Dennis Nice, I forgot about floor-dividing. Is there a chance the parameters could be mutually optimized to be shorter?

I'm not really sure, but multiplying instead of using 'and' (for the second thing) might be shorter.

@xnor Indeed. lambda n:n**.3335//.55 works, saving two more bytes.

@J843136028 The and is for logical short-circuiting in order to terminate. All recursive definitions need something that can avoid evaluating the recursive call at some point.

@Dennis You should post it!

Alright, done. :)

J, 12 bytes
2>.@-~3!inv]

There might be a golfier way to do this, but this is a lovely opportunity to use J's built-in function inversion.
Try it online!
How it works
2>.@-~3!inv]  Monadic verb. Argument: n

           ]  Right argument; yield n.
      3       Yield 3.
       !inv   Apply the inverse of the ! verb to n and 3. This yields a real number.
              x!y computes Π(y)/(Π(y-x)Π(x)), where Π is the extnsion of the
              factorial function to the real numbers. When x and y are non-negative
              integers, this equals yCx, the x-combinations of a set of order y.
 >.@-~        Combine the ceil verb (>.) atop (@) the subtraction verb (-) with
              swapped arguments (~).
2             Call it the combined verbs on the previous result and 2.

Python, 22 bytes
lambda n:n**.3335//.55

Heavily inspired by @xnor's Python answer.
Try it online!

Jelly, 7 bytes
R‘c3<¹S

Try it online!
How it works
R‘c3<¹S  Main link. Argument: n

R        Range; yield [1, ..., n].
 ‘       Increment; yield [2, ..., n+1].
  c3     Combinations; yield [C(2,3), ..., C(n+1,3)].
    <¹   Yield [C(2,3) < n, ..., C(n+1,3) < n].
      S  Sum; count the non-negative values of k for which C(k+2,3) < n.

Sometimes I wonder, what can Jelly not do?

One of these days someone is going to be like "Code Golf a fully featured MMO" and Dennis is going to post "Jelly, 29 bytes" or something stupid like that.

JavaScript (ES6), 33 bytes
n=>(F=k=>k<n?F(k+3*k/i++):i)(i=1)

Based on the recursive formula:
a(1) = 1
a(i) = (i + 3) * a(i - 1) / i

The second expression can also be written as ...
a(i) = a(i - 1) + 3 * a(i - 1) / i

... which is the one that we are using here.
a(i - 1) is actually stored in the k variable and passed to the next iteration until k >= n.
Test cases

let f =

n=>(F=k=>k<n?F(k+3*k/i++):i)(i=1)

console.log(f(1));   // ->  1
console.log(f(5));   // ->  3
console.log(f(75));  // ->  7
console.log(f(100)); // ->  8
console.log(f(220)); // ->  10
console.log(f(221)); // ->  11
console.log(f(364)); // ->  12

This is sneakily short! Good job.

@FlipTack My first attempt was based on the formula you used. I had to change my plans. ;-)

Ruby, 26 bytes
Edit: alternate version, still 26 bytes
->n{(n**0.3333*1.82).to_i}

Original version
->n{((n*6)**0.33355).to_i}

Uses the fact that T(x) = x(x+1)(x+2)/6 = ((x+1)**3-(x+1))/6 which is very close to (x+1)**3/6.
The function simply multiplies by 6, finds a slightly tweaked version of the cube root (yes 5 decimal places are required) and returns the result truncated to an integer.
Test program and output
f=->n{((n*6)**0.33355).to_i}
[1,4,10,20,35,56,84,120,165,220,286,364].map{|i|p [i,f[i],f[i+1]]}

[1, 1, 2]
[4, 2, 3]
[10, 3, 4]
[20, 4, 5]
[35, 5, 6]
[56, 6, 7]
[84, 7, 8]
[120, 8, 9]
[165, 9, 10]
[220, 10, 11]
[286, 11, 12]
[364, 12, 13]

0.3336 seems to work for the original version. (Edit: Never mind, Dennis points out I was forgetting about 364.)

JavaScript, 36 33 bytes
-3 bytes thanks to Luke (making the function curried)
n=>f=i=>n<=i/6*-~i*(i+2)?i:f(-~i)

This is an unnamed lambda function which can be assigned to func and called with func(220)(), as described in this meta post. My original, non-curried function looks like this:
f=(n,i)=>n<=-~i*i/6*(i+2)?i:f(n,-~i)

This answer uses the fact that xth tetrahedral number can be found with the following function:
\$f(x) = \frac{x}6(x+1)(x+2)\$
The function works by recursively increasing i, and finding tetrahedral(i), until it's larger than or equal to n (the number of presents given).
When called with one argument as expected, i = undefined, and therefore is not larger than n. This means f(n,-~i) is executed, and -~undefined evaluates to 1, which sets off the recursion.

Test Snippet:

func = n=>f=i=>n<=i/6*-~i*(i+2)?i:f(-~i)

var tests = [1, 5, 75, 100, 220, 221, 364];
tests.forEach(n => console.log(n + ' => ' + func(n)()));

I was about to post the exact same answer. Beat me by 2 mins. Good job!

You can save 3 bytes by currying: n=>g=i=>n<=i/6*++i*++i?i-2:g(~-i). You'd call it like f(2)().

@Luke good spot, my curried function wasn't so short. Are you sure you don't want to post that as your own answer?

Nah, I'd do it if we were using a different formula, but now our solutions are nearly identical. I'd rather help you get on the same level as Arnauld. ;-)

i=>n<=i Beautiful ;-)

MATL, 12 11 bytes
`G@H+IXn>}@

Try it online!
Explanation
`       % Do...while
  G     %   Push input, n
  @     %   Push iteration index (1-based), say m
  H     %   Push 2
  +     %   Add
  I     %   Push 3
  Xn    %   Binomial coefficient with inputs m+2, 3
  >     %   Is n greater than the binomial coefficient? If so: next iteration
}       %   Finally (execute after last iteration, before exiting the loop)
  @     %   Push last iteration index. This is the desired result
        % End (implicit)
        % Display (implicit)

05AB1E, 10 bytes
XµNÌ3c¹‹_½

Try it online!
Explanation
Xµ          # loop until counter equals 1
  NÌ3c      # binomial_coefficient(iteration_index+2,3)
      ¹     # push input
       ‹_   # not less than
         ½  # if true, increment counter
            # output last iteration index

Wow, binom is much smarter than [N2Ý+P6÷¹Q#N>, nice one.

Pyke, 11 bytes
#3RL+B6f)lt

Try it here!
#3RL+B6f)   -  while rtn <= input as i:
 3RL+       -     i+j for j in range(3)
     B      -    product(^)
      6f    -   ^/6
         lt - len(^)-1

Japt, 12 bytes
1n@*6§X³-X}a

Test it online! or Verify all test cases at once
How it works
1n@*6§X³-X}a  // Implicit: U = input integer
  @       }a  // Find the smallest non-negative integer X which satisfies this condition:
      X³-X    //   (X ^ 3) - X
     §        //   is greater than or equal to
   *6         //   U * 6.
1n            // Subtract 1 from the result.
              // Implicit: output result of last expression

This is a simplification of the tetrahedral formula several other answers are using:
f(x) = (x)(x + 1)(x + 2)/6

By substituting x - 1 for x, we can simplify this considerably:
f(x) = (x - 1)(x)(x + 1) / 6
f(x) = (x - 1)(x + 1)(x) / 6
f(x) = (x^2 - 1)(x) / 6
f(x) = (x^3 - x) / 6

Therefore, the correct result is one less than the smallest integer x such that (x^3 - x) / 6 is greater than or equal to the input.
13-byte solution, inspired by @xnor's answer:
p.3335 /.55 f

A few more solutions @ETHproductions and I played around with
J+@*6§X³-X}a
@*6§X³-X}a -1
@§X/6*°X*°X}a
_³-V /6¨U}a -1
§(°V nV³ /6?´V:ß
§(°VV³-V /6?´V:ß

Test it here.

Mathematica, 26 bytes
(0//.i_/;i+6#>i^3:>i+1)-1&

Unnamed function taking a nonnegative integer argument and returning a nonnegative integer (yeah, it works for day 0 too). We want to find the smallest integer i for which the input # is at most i(i+1)(i+2)/6, which is the formula for the number of gifts given on the first i days. Through mild algebraic trickery, the inequality # ≤ i(i+1)(i+2)/6 is equivalent to (i+1) + 6# ≤ (i+1)^3. So the structure 0//.i_/;i+6#>i^3:>i+1 starts with a 0 and keeps adding 1 as long as the test i+6#>i^3 is satisfied; then (...)-1& subtracts 1 at the end (rather than spend bytes with parentheses inside the inequality).
If we let the 12 Days of Christmas continue, we can handle about 65536 days before the built-in recursion limit for //. halts the process ... that's about 4.7 * 10^13 days, or about ten times the age of the universe thus far....

J, 9 bytes
I.~3!2+i.

Try it online!
This is more inefficient than using the inverse of factorial but happens to be shorter.
For example, if the input integer is n = 5, make the range [2, n+1].
2 3 4 5 6 choose 3
0 1 4 10 20

These are the first 5 tetrahedral numbers. The next step is to determine which interval (day) n belongs to. There are n+1 = 6 intervals.
0 (-∞, 0]
1 (0, 1]
2 (1, 4]
3 (4, 10]
4 (10, 20]
5 (20, ∞)

Then n = 5 belongs to interval 3 which is (4, 10] and the result is 3.
Explanation
I.~3!2+i.  Input: integer n
       i.  Range [0, n)
     2+    Add 2 to each
   3!      Combinations nCr with r = 3
I.~        Interval index of n

Python, 43 bytes
f=lambda n,i=0:n*6>-~i*i*(i+2)and-~f(n,i+1)

Saved 5 bytes thanks to @FlipTack and another 3 thanks to @xnor!

This gives f(220)=11, which should be f(220)=10.

Oh, I was using Python 2. This needs Python 3 to avoid floor division, though perhaps you can multiply on the other side instead to make it version-agnostic.

I think you can do  and-~f(n,i+1) for and f(n,i+1)or i. Strangely, it's usually shorter when you're counting up a variable recursively not to return it, but to instead increment the output recursively.

APL (Dyalog Classic), 8 bytes
+\⍣2∘⍳⍳⊢

My first time using APL, thanks to H.PWiz for shortening it into a train
Essentially a port of the Jelly answer
Explanation
+\⍣2∘⍳⍳⊢
    ∘⍳    Numbers from 1 to input inclusive
+\        Cumulative reduce with addition, gets triangular numbers
  ⍣2      Repeat (does it again) to get the tetrahedral numbers
      ⍳⊢  Index of the input in that list

Try it online!

Unfortunately I don't think this is a valid solution as it fails for p = 221. It will only work for values of p that are exactly tetrahedral numbers

Python 3, 48 46 bytes
f=lambda x,i=1:f(x,i+1)if(i+3)*i+2<x/i*6else i

@FlipTack Argh! I'll fix it in a sec... nobody downvote, please.

You can prevent any downvoting by deleting your answer. You will then still be able to edit the answer and undelete it once it's fixed.

Also, this still doesn't do what the challenge asks. An input of 221 will crash it.

I've tested this on TIO and it crashes on all inputs. Is this my problem or is this happening to anyone else?

It worked for me. I'll test it again.

@JackBates Bother. I thought it only had to work for tetrahedron numbers. Fixed.

Why are people voting for this rubbish? Vote for @xnor's implementation instead; both of their methods are amazing.

SmileBASIC, 43 bytes
INPUT X
WHILE X>P
I=I+1
R=R+I
P=P+R
WEND?I

I is the day, R is the ith triangular number, and P is the ith tetrahedral number (number of presents).
I think a similar answer in another language, perhaps:
x=>{while(x>p)p+=r+=++i;return i} could be pretty good.

You want ?I at the end, don't you?

Mathematica, 31 25 bytes
Floor@Root[x^3-x-6#+6,1]&

Haskell, 21 23 bytes
floor.(**(1/3)).(*6.03)

Edit: As xnor pointed out, the original solution (floor.(/0.82).(**0.4)) didn't work between the days of christmas

This gives the wrong answer on many inputs, for example 221.

Itr, 11 bytes
#äµS¹µS>S1+
online interpreter
Explanation
#            ; read a number `n`  from standard input
 ä           ; duplicate that number
  µ          ; apply for all integers in the range [1,...,n]
   S         ; replace each element `k` of the range with the sum from 1 to `k`
    ¹        ; push all no-empty prefixes of that list
     µS      ; sum up the elements, this will give the list of the first `n` tetrahedral numbers
       >     ; vectorized comparison
        S    ; sum up, this will count the number of triangle numbers that are smaller than `n`
         1+  ; offset by one to get the right number

Bash + bc, 44  bytes
bc -l <<< "f=e(.33359*l($1*6));scale=0;f/1"

Batch, 69 bytes
@set/an=d=t=0
:l
@set/at+=d+=n+=1
@if %t% lss %1 goto l
@echo %n%

Manually calculates tetrahedronal numbers.

Pyth 11 bytes
/^Q.3335.55

Try it online!
pretty much just translated Dennis' answer into Pyth

R, 19 characters
floor((n*6)^.33359)

based on xnor's answer in Python.

QBIC, 19 bytes
This steals @xnor 's formula:
:?int((a*6)^.33359)

I tried dialing down the resolution to .3336 to save a byte, but that fails on the final testcase.

Husk, 6 bytes
V≥¹∫∫ḣ

Try it online! or Verify all test cases
Explanation
V≥¹∫∫ḣ
     ḣ range 1..n
   ∫∫  cumulative sum, twice
V      index of first element that is
 ≥¹    greater than or equal to the input


text:
Inverse Pi function
The Pi function is an extension of the factorial over the reals (or even complex numbers). For integers n, Π(n) = n!, but to get a definition over the reals we define it using an integral:

In this challenge we will invert the Π function.
Given a real number z ≥ 1, find positive x such that Π(x) = z. Your answer must be accurate for at least 5 decimal digits.

Examples:
120 -> 5.0000
10 -> 3.39008
3.14 -> 2.44815
2017 -> 6.53847
1.5 -> 1.66277

Note that more often people use the Gamma (Γ) function. Π(x) = Γ(x+1). But IMO Γ is a shifted abomination, and Π is the true extension of the factorial.

Wellp, that series expansion is enough to scare me... http://i.imgur.com/ttgzDSJ.gif

All of the examples you give have other solutions as well, for example 120 -> -0.991706. This is because Π(x) goes to infinity as x goes to -1 from the right. Perhaps you mean to insist that x>0 as well.

@GregMartin Added as well.

For the record, Mathematica doesn't seem to have a well-behaved builtin for this; all attempts to craft one run into issues with what domain of $\Pi$ or $\Gamma$ we should be sticking to. Fail!

@orlp:  Π has also the meaning of Sequence Product, the same way Σ has the meaning of Sequence Summation. May be Γ was used just to not to be equal to Π

@GregMartin you can constrain it to positive numbers easily though.

@sergiol I'm not arguing that the symbol sucks. The symbol doesn't matter. I'm comparing the definitions of the Gamma and Pi functions. Gamma sucks, because it's always offset by 1.

There are some reasons to prefer the shifted version, despite it seems unnatural. See e.g. this answer on MathOverflow as well as others on that page.

Mathematica, 17 15 27 bytes
FindInstance[#==x!&&x>0,x]&

Output looks like {{x -> n}}, where n is the solution, which may not be allowed.

Pyth, 4 bytes
.I.!

A program that takes input of a number and prints the result.
Test suite
How it works
.I.!    Program. Input: Q
.I.!GQ  Implicit variable fill
.I      Find x such that:
  .!G    gamma(x+1)
     Q   == Q
        Implicitly print

MATL, 13 bytes
1`1e-5+tQYgG<

This uses linear seach in steps of 1e-5 starting at 1. So it is terribly slow, and times out in the online compiler.
To test it, the following link replaces the 1e-5 accuracy requirement by 1e-2. Try it online!
Explanation
1        % Push 1 (initial value)
`        % Do...while
  1e-5   %   Push 1e-5
  +      %   Add
  t      %   Duplicate
  QYg    %   Pi function (increase by 1, apply gamma function)
  G<     %   Is it less than the input? If so: next iteration
         % End (implicit)
         % Display (implicit)

GeoGebra, 25 bytes
NSolve[Gamma(x+1)=A1,x=1]

Entered in the CAS input, and expects input of a number in spreadsheet cell A1. Returns a one-element array of the form {x = <result>}.
Here is a gif of the execution:

How it works
NumericallySolve the following equation: Gamma(x+1)=A1, with starting value x=1.

Is it guaranteed to return a positive number, and does it work for 1.5, which has broken several answers?

@Pavel I can confirm that it works for 1.5. I haven't been able to find out which algorithm GeoGebra uses for numerical solving, but the initial value of x=1 has given purely positive answers for every value I have tried.

J, 86 33 bytes
((]-(-~^.@!)%[:^.@!D.1])^:_>:)@^.

Uses Newton's method with log Pi to avoid overflow.
This is the previous version that computes log Gamma using Stirling's approximation. The step size (1e3) and number of terms in log Gamma (3) can be increased for possibly higher accuracy at the cost of performance.
3 :'(-(k-~g)%%&1e3(g=:((%~12 _360 1260 p.&:%*:)+-+^~-&^.%:@%&2p1)@>:)D:1])^:_>:k=:^.y'

Another version that computes the coefficient terms on the fly
3 :'(-((-^.y)+g)%%&1e3(g=:((%~(((%1-^@-)t:%]*<:)+:>:i.3)p.%@*:)+(*^.)-]+-:@^.@%&2p1)@>:)D:1])^:_>:^.y'

Try it online! and to see the terms converge.
Explanation
((]-(-~^.@!)%[:^.@!D.1])^:_>:)@^.  Input: float y
(                            )@^.  Operate on log(y)
                           >:        Increment, the initial guess is log(y)+1
 (                     )^:_          Repeat until convergence starting with x = log(y)+1
                      ]                Get x
               ^.@!                    The log Pi verb
             [:    D.1                 Approximate its first derivative at x
       ^.@!                            Apply log Pi to x
     -~                                Subtract log(y) from it
            %                          Divide it by the derivative
  ]-                                   Subtract it from x and use as next value of x

Mathematica, 21 bytes
FindRoot[#-x!,{x,1}]&

FindRoot applies Newton's method internally when there is an initial value.
The two methods below apply Newton's method directly.
Alternative using FixedPoint 45 bytes
FixedPoint[#-(#!-y)/Gamma'[#+1]&,Log[y=#]+1]&

A more precise implementation of Newton's method for solving this since Mathematica can compute the derivative directly instead of approximating it.
Using rules to replace repeatedly would be shorter, but there is a limit (65536) to how many iterations it can perform that might be hit whereas FixedPoint does not have a limit.
Alternative using rules, 38 bytes
Log[y=#]+1//.x_->x-(x!-y)/Gamma'[x+1]&

MATLAB, 59 bytes
@(x)fminsearch(@(t)(gamma(t+1)-x)^2,1,optimset('TolF',eps))

This is an anonymous function that finds the minimizer of the squared difference betweeen the Pi function and its input, starting at 1, with very small tolerance (given by eps) to achieve the desired precision.
Test cases (run on Matlab R2015b):
>> @(x)fminsearch(@(t)(gamma(t+1)-x)^2,1,optimset('TolF',eps))
ans =
    @(x)fminsearch(@(t)(gamma(t+1)-x)^2,1,optimset('TolF',eps))
>> f = ans; format long; f(120), f(10), f(3.14), f(2017)
ans =
   5.000000000000008
ans =
   3.390077650547032
ans =
   2.448151165246967
ans =
   6.538472664321318

You could try it online in Octave, but unfortunately some of the results lack the required precision.

Jelly, 34 bytes
Ḋ!Æl_®
ȷİ‘×;µ!ÆlI÷I÷@Ç_@ḊḢ
Æl©‘ÇÐĿ

Try it online! or View the intermediate values as they converge.
An implementation of J's combination of Newton's method and derivative approximation (secant method) to compute the inverse of Π(n).
It solves for the inverse of log(Π(n)) instead in order to avoid overflow.
It starts with an initial guess x0 = y+1 where y = log(Π(n)). Then it iterates until convergence using xn+1 = xn - (log(Π(xn)) - y) / (log((Π(1.001 * xn)) - log(Π(xn))) / (0.001 * xn)).

I get an error with input 1.5

@LuisMendo Wow that is a good catch! It occurs since one of the intermediate values is ~65807 which is a huge value after gamma is applied, and Python overflows. The same occurs in J since it relies on the same computation.

PARI/GP, 30 bytes
x->solve(t=1,x+1,gamma(t+1)-x)

Finds solution between 1 andx+1. Unfortunately, x is not big enough as upper bound for input like 1.5.

Mathematica, 26 Bytes
Yet another Mathematica solution!
Equation solving can always be turned into a minimization problem.
NArgMin[{(#-x!)^2,x>0},x]&

Finds the argument that minimizes the difference between the left and right sides of the equation.
Using NArgMin rather than NMinimize forces the output to just be the desired result rather than the usual verbose rule-based output (and it saves a byte!)

C with libm, 111
Update - fixed for input 1.5.
f(double *z){double u=2**z,l=0,g=u,p=0;for(;log(fabs(g-p))>-14;)p=g,g=(u+l)/2,u=tgamma(g+1)>*z?g:(l=g,u);*z=g;}

gamma(x+1) is a monotonically increasing function over the range in question, shis is just a binary search until the difference between successive values is small. The starting lower bound is 0 and the starting upper bound is 2*x.
Input and output is via a pointer to a double passed to the function.
I'm pretty sure this can be golfed deeper - in particular I don't think I need 4 local doubles, but so far I'm not seeing an easy way to reduce this.
Try it online - Builds (linking with libm) and runs in a bash script.
Mildly ungolfed:
f(double *z){
    double u=2**z,l=0,g=u,p=0;
    for(;log(fabs(g-p))>-14;){
        p=g;
        g=(u+l)/2;
        u=tgamma(g+1)>*z?g:(l=g,u);*z=g;
    }
}