text:
Mutually Exclusive Quines
Your challenge is simple. Write two programs that share no characters which output each other.
Example
Two programs P and Q are mutually exclusive quines if:

P outputs Q
Q outputs P
There is no character c which belongs to both P and Q
Each program P and Q are proper quines

This counts empty quines and quines that read their own (or the other's) source code as invalid.

More rules

The shortest combined length of these programs wins. That is, size(P) + size(Q) is your score, and the lowest score wins.
Both programs are in the same language
Each program may be a full program or function, and they need not be the same.

For example, P may be a full program and Q may be a function.

Verification
This Try it online! snippet here can verify whether or not two programs are mutually exclusive. The inputs are put in the first two arguments.

Related.

Related, Related.

I would presume that two programs that read one another's source are banned as well.

@Giuseppe Yes.

I'd love to see a non-esolang answer to this challenge. (I had a bit of a thought about how to do that, but so far I haven't seen a way. It might be possible in Forth though, since it's not case sensitive and doesn't rely much on non-alphabetic characters.)

Can I pass the same flag to the interpreter/compiler of both programs?

@BlackCap please elaborate?

I don't actually have an answer that uses this, but would something like bc -not and the programs 0 and 1 be an acceptable answer if I pay for the flag?

@BlackCap I still don't quite get your question. Are you asking if you can add different arguments to the two programs? Or are you asking if arguments are allowed?

If I can pass the same argument, not to the programs themselves, but to the compiler of both programs. Typically compiler flags are allowed if you pay for them, but for this challenge you might argue it goes against the mutually exclusive rule.

There is an obvious problem with applying the part of the proper quine definition that says there must be a part of the program that encodes something other than itself. That only makes sense for this kind of variant if you interpret it as "after going a full cycle". But if you do that, then I think @BlackCap's suggestion is disallowed.

@BlackCap The rules about flags had been changed last I heard. They now cost nothing but which flags are used is considered part of the language choice. (So you'd need to specify something like "bc with -not flag" as the language.)

@ØrjanJohansen 's suggestion makes sense. I suppose then if you were to use flags, they must be consistent.

><>, Score: 41+41 = 82
Edit: both contained a 3. Fixed
'd3*}>a!o-!<<8:5@lI55>@z:5ll55>>q:>|q::|,

and
"r00gr40g44++bb+0p64++?b6+0.22#eW4s )Z

Try it online! (swap the lines to get the other output) With verification this time!
><> is an especially hard language to use here, as there is only one way to output characters, the command o. Fortunately, we can use the put command to place an o in the source code during execution, like in my Programming in a Pristine World answer.
This one took a lot of trial and error. I started off with the two mutually exclusive programs:
'd3*}>N!o-!<<data

and
"r00gr40g8+X0pN+?Y0.data

Each one transforms itself and its data by N, the first one subtracting and the second adding. It then outputs this in reverse. The point is that the data after each program is the other program in reverse, shifted by N. (X is the cell number where the program needs to put the o and Y is the cell where the pointer loops back to. ? is where the o is put).
Both follow the same structure, represented in different ways. They run a string literal over the entire code, adding it to the stack. They recreate the string literal command they used and put it at the bottom of the stack. They loop over the stack, adding/subtracting N to each character and printing them.
The first program uses ' as the string literal, and the simple d3*} to create the value 39 and push it to the bottom of the stack. The second uses " as the string literal with the same function. It reverses the stack, gets the character at cell 0,0 and reverses the stack again. It then gets the value at cell 4,0 (g) and adds 8 to it to get o and puts that at X.
Both programs use a different method of looping. The first program uses the skip command (!) to run only half the instructions while going left, reverses direction and runs the other half. The second uses the jump command (.) to skip backwards to the start of the loop at cell Y. Both of these run until there are no more items on the stack and the program errors.
I ran into a number of problems with most of the lower values of N, because shifting one character would turn it into another character essential for that program (and therefore couldn't be used as data for the other program) or two characters from the two programs would shift into the same character. For example:

++1 = , = --1
.+2 = 0
* = --3
g+4 = k =  o-4

etc.
Eventually I got to 10 (a), where I was able to avoid these issues. There might be a shorter version where the shifts are reversed, and the first program is adding N while the second subtracts it. This might be worse off though, as the first program is generally on the lower end of the ASCII scale, so subtracting is better to avoid conflicts.

Forth (64-bit little-endian gforth), 428 + 637 = 1065 bytes
s"	:	l	bl	-	;	:	m	l	emit	;	:	s	space	;	:	z	m	m	m	m	s	;	:	p	.	't	'i	'm	'e	z	;	'e	'r	'e	'h	z	:	q	>r	char	l	bl	l	do	dup	@	.	'L	m	s	cell+	loop	r>	.	;	:	n	'e	'p	'y	't	z	;	q	;	's	p	'B	l	p	#tab	p	'p	'u	'd	'Q	char+	z	n	'B	l	p	n":	l	bl	-	;	:	m	l	emit	;	:	s	space	;	:	z	m	m	m	m	s	;	:	p	.	't	'i	'm	'e	z	;	'e	'r	'e	'h	z	:	q	>r	char	l	bl	l	do	dup	@	.	'L	m	s	cell+	loop	r>	.	;	:	n	'e	'p	'y	't	z	;	q	;	's	p	'B	l	p	#tab	p	'p	'u	'd	'Q	char+	z	n	'B	l	p	n

HERE 3245244174817823034 , 7784873317282429705 , 665135765556913417 , 7161128521877883194 , 682868438367668581 , 679209482717038957 , 680053688600562035 , 678116140452874542 , 682868623551327527 , 680649414991612219 , 682868636436227367 , 7136360695317203258 , 7809815063433470312 , 8458896374132993033 , 5487364764302575984 , 7810758020979846409 , 680166068077538156 , 4181938639603318386 , 8081438386390920713 , 8793687458429085449 , 2812844354006760201 , 7784826166316108147 , 676210045490917385 , 681493840106293616 , 7521866046790788135 , 679491013524025953 , 7928991804732031527 , 216 115 EMIT 34 EMIT 9 EMIT 2DUP TYPE 34 EMIT TYPE

Try it online!
Verification script
Thanks to @Nathaniel for the idea of using Forth - he reminded me in the comments that Forth is not case-sensitive. Then came the mood swings - I've been finding reasons why this will not work, followed by solutions to these problems, again and again. All while spinning my indoor training bike like an oversided and misshaped fidget spinner (you just have to grab one end of the handle bar and tilt it a bit).
Before writing these programs, I drafted what characters can be used by which program. Specifically, the second program can only use uppercase letters, decimal digits, tabs, and commas. This would mean that the first program is all lowercase, but I used some uppercase letters for their ASCII values.
Because tabs are unwieldy, I'll use spaces in the explanation instead.
The first program is of the form s" code"code - the s" starts a string literal, which is then processed by the second copy of the code - a standard quine framework. However, instead of outputting its own source code, it will create the other program, which looks like this:

HERE
For each 8 bytes in the original string, 64-bit-number-literal ,
length-of-the-string
115 EMIT 34 EMIT 9 EMIT 2DUP TYPE 34 EMIT TYPE

This uses Forth's data space. HERE returns the pointer to the end of the currently allocated data space area, and , appends a cell filled with a number to it. Therefore, the first three bullet points can be seen like a string literal created using s". To finish the second program off:

EMIT outputs a character given its ASCII value, so:

115 EMIT prints a lowercase s
34 EMIT prints the quote character "
9 EMIT prints a tab

2DUP duplicates the top two elements on the stack ( a b -- a b a b ), here it's the pointer to and the length of the string
TYPE prints a string to output the first copy of the code
34 EMIT prints the closing quote ", and finally
TYPE outputs the second copy of the code

Let's see how the first program works. In many cases numbers have to be avoided, which is done using the 'x gforth syntax extension for character literals, and sometimes subtracting the ASCII value of space, which can be obtained using bl:
s" ..."      \ the data
: l bl - ;   \ define a word, `l`, that subtracts 32
: m l emit ; \ define a word, `m`, that outputs a character. Because 32 is
             \ subtracted using `l`, lowercase characters are converted to
             \ uppercase, and uppercase characters are converted to some
             \ symbols, which will become useful later
: z m m m m space ; \ `z` outputs four characters using `m`, followed by a
                    \ space. This is very useful because all words used in the
                    \ second program are four characters long
: p . 't 'i 'm 'e z ; \ define a word, `p`, that, given a number, outputs that
                      \ number, followed by a space, `EMIT`, and another space
'e 'r 'e 'h z \ here is where outputting the second program starts - `HERE `
: q \ define a helper word, `q`, that will be called only once. This is done
    \ because loop constructs like do...loop can't be used outside of a word.
  >r \ q is called with the address and the length of the data string. >r saves
     \ the length on the return stack, because we don't need it right now. While
     \ it might seem like this is too complicated to be the best way of doing
     \ this for codegolf, just discaring the length would be done using four
     \ characters - `drop`, which would give you the same bytecount if you could
     \ get the length again in... 0 characters.
  char l \ get a character from after the call to q, which is `;`, with the
         \ ASCII value of $3B, subtract $20 to get $1B, the number of 64-bit
         \ literals necessary to encode the string in the second program.
  bl l \ a roundabout way to get 0
  do   \ iterate from 0 (inclusive) to $1B (exclusive)
    \ on the start of each iteration, the address of the cell we are currently
    \ processing is on the top of the stack.
    dup @ . \ print the value. The address is still on the stack.
    'L m space \ the ASCII value of L is exactly $20 larger than the one of ,
    cell+ \ go to the next cell
  loop
  r> . \ print the length of the string
;
: n 'e 'p 'y 't z ; \ define a word, `n`, that outputs `TYPE`
q ; \ call q, and provide the semicolon for `char` (used to encode the length
    \ of the string in 64-bit words). Changing this to an uppercase U should
    \ make this work on 32-bit systems, but I don't have one handy to check that
's p \ print the code that outputs the lowercase s
'B l p \ likewise, 'B l <=> $42 - $20 <=> $22 <=> the ASCII value of a comma
#tab p \ print the code that outputs a tab
'p 'u 'd 'Q char+ z \ char+ is the best way to add 1 without using any digits.
                    \ it is used here to change the Q to an R, which can't be
                    \ used because of `HERE` in the second program. R has an
                    \ ASCII value exactly $20 larger than the ASCII value of 2,
                    \ so this line outputs the `2DUP`.
n 'B l p n \ output TYPE 34 EMIT TYPE to finish the second program. Note the
           \ that the final `n` introduces a trailing space. Trying to remove
           \ it adds bytes.

To finish this off, I'd like to say that I tried using EVALUATE, but the second program becomes larger than both of the ones presented above. Anyway, here it is:
: s s" ; s evaluate"s" : l bl - ; : m l emit ; : d here $b $a - allot c! ; : c here swap dup allot move ; : q bl l do #tab emit dup @ bl l u.r cell+ #tab emit 'L m loop ; here bl 'B l 's bl 's bl 'Z l d d d d d d d -rot c bl 'B l 's 'B l d d d d s c 'B l d c 'e 'r 'e 'h m m m m 'A q #tab emit 'e 'p 'y 't m m m m"; s evaluate

If you manage to golf this down enough to outgolf my s" ..."... approach, go ahead and post it as your own answer.

Great! I'm happy that my comment sparked this solution!

Perl, (311+630 = 941 bytes) 190+198 = 388 bytes
Both programs print to standard output.
The first perl program contains mostly printable ASCII characters and newlines, and it ends in exactly one newline, but the two letter ÿ represents the non-ASCII byte \xFF:
@f='^"ÿ"x92;@f=(@f,chr)for 115,97,121,36,126,191,153,194,216,113;print@f[1..5,5,10,5..9,0,9,0,5]'^"ÿ"x92;@f=(@f,chr)for 115,97,121,36,126,191,153,194,216,113;print@f[1..5,5,10,5..9,0,9,0,5]

The second one contains mostly non-ASCII bytes, including several high control characters that are replaced by stars in this post, and no newlines at all:
say$~~q~¿*ÂØ¡Ý*Ý*ÆÍÄ¿*Â×¿*Ó***Ö***ßÎÎÊÓÆÈÓÎÍÎÓÌÉÓÎÍÉÓÎÆÎÓÎÊÌÓÎÆËÓÍÎÉÓÎÎÌÄ*****¿*¤ÎÑÑÊÓÊÓÎÏÓÊÑÑÆÓÏÓÆÓÏÓÊ¢Ø¡Ý*Ý*ÆÍÄ¿*Â×¿*Ó***Ö***ßÎÎÊÓÆÈÓÎÍÎÓÌÉÓÎÍÉÓÎÆÎÓÎÊÌÓÎÆËÓÍÎÉÓÎÎÌÄ*****¿*¤ÎÑÑÊÓÊÓÎÏÓÊÑÑÆÓÏÓÆÓÏÓÊ¢~

A hexdump of the first program with xxd is:
00000000: 4066 3d27 5e22 ff22 7839 323b 4066 3d28  @f='^"."x92;@f=(
00000010: 4066 2c63 6872 2966 6f72 2031 3135 2c39  @f,chr)for 115,9
00000020: 372c 3132 312c 3336 2c31 3236 2c31 3931  7,121,36,126,191
00000030: 2c31 3533 2c31 3934 2c32 3136 2c31 3133  ,153,194,216,113
00000040: 3b70 7269 6e74 4066 5b31 2e2e 352c 352c  ;print@f[1..5,5,
00000050: 3130 2c35 2e2e 392c 302c 392c 302c 355d  10,5..9,0,9,0,5]
00000060: 275e 22ff 2278 3932 3b40 663d 2840 662c  '^"."x92;@f=(@f,
00000070: 6368 7229 666f 7220 3131 352c 3937 2c31  chr)for 115,97,1
00000080: 3231 2c33 362c 3132 362c 3139 312c 3135  21,36,126,191,15
00000090: 332c 3139 342c 3231 362c 3131 333b 7072  3,194,216,113;pr
000000a0: 696e 7440 665b 312e 2e35 2c35 2c31 302c  int@f[1..5,5,10,
000000b0: 352e 2e39 2c30 2c39 2c30 2c35 5d0a       5..9,0,9,0,5].

And a hexdump of the second program is:
00000000: 7361 7924 7e7e 717e bf99 c2d8 a1dd 00dd  say$~~q~........
00000010: 87c6 cdc4 bf99 c2d7 bf99 d39c 978d d699  ................
00000020: 908d dfce ceca d3c6 c8d3 cecd ced3 ccc9  ................
00000030: d3ce cdc9 d3ce c6ce d3ce cacc d3ce c6cb  ................
00000040: d3cd cec9 d3ce cecc c48f 8d96 918b bf99  ................
00000050: a4ce d1d1 cad3 cad3 cecf d3ca d1d1 c6d3  ................
00000060: cfd3 c6d3 cfd3 caa2 d8a1 dd00 dd87 c6cd  ................
00000070: c4bf 99c2 d7bf 99d3 9c97 8dd6 9990 8ddf  ................
00000080: cece cad3 c6c8 d3ce cdce d3cc c9d3 cecd  ................
00000090: c9d3 cec6 ced3 ceca ccd3 cec6 cbd3 cdce  ................
000000a0: c9d3 cece ccc4 8f8d 9691 8bbf 99a4 ced1  ................
000000b0: d1ca d3ca d3ce cfd3 cad1 d1c6 d3cf d3c6  ................
000000c0: d3cf d3ca a27e                           .....~

In the second program, the quoted string (189 bytes long, delimited by tildes) is the entire first program except the final newline, only encoded by bitwise complementing each byte.  The second program simply decodes the string by complementing each of the bytes, which the ~ operator does in perl.  The program prints the decoded string followed by a newline (the say method adds a newline).
In this construction, the decoder of the second program uses only six different ASCII characters, so the first program can be practically arbitrary, as long as it only contains ASCII characters and excludes those six characters.  It's not hard to write any perl program without using those five characters.   The actual quine logic is thus in the first program.
In the first program, the quine logic uses a 11 word long dictionary @f, and assembles the output from those words.  The first words repeats most of the source code of the first program.  The rest of the words are specific single characters.  For example, word 5 is a tilde, which is the delimiter for the two string literal in the second program.  The list of numbers between the brackets is the recipe for which words to print in what order.  This is a pretty ordinary general construction method for quines, the only twist in this case is that the first dictionary words is printed with its bytes bitwise complemented.

Haskell, 306 + 624 = 930 bytes
Program 1: An anonymous function taking a dummy argument and returning a string.
(\b c()->foldr(\a->map pred)b(show()>>c)`mappend`show(map(map fromEnum)$tail(show c):pure b))"İĴİóđđđÝöÝâÝæÝääē××êääē××İēÀħđĮâħēĕóİóòòĮááħááđéêâéêēááĮÀħ""(\b c()->foldr(\a->map pred)b(show()>>c)`mappend`show(map(map fromEnum)$tail(show c):pure b))"

Try it online!
Program 2: q[[40,...]] at the end is an anonymous function taking a dummy argument and returning a string.
z~z=[[['@','0'..]!!4..]!!z]
q[x,q]_=z=<<x++q++[34,34]++x
q[[40,92,98,32,99,40,41,45,62,102,111,108,100,114,40,92,97,45,62,109,97,112,32,112,114,101,100,41,98,40,115,104,111,119,40,41,62,62,99,41,96,109,97,112,112,101,110,100,96,115,104,111,119,40,109,97,112,40,109,97,112,32,102,114,111,109,69,110,117,109,41,36,116,97,105,108,40,115,104,111,119,32,99,41,58,112,117,114,101,32,98,41,41,34],[304,308,304,243,273,273,273,221,246,221,226,221,230,221,228,228,275,215,215,234,228,228,275,215,215,304,275,192,295,273,302,226,295,275,277,243,304,243,242,242,302,225,225,295,225,225,273,233,234,226,233,234,275,225,225,302,192,295]]

Try it online!
Character set 1 (includes space):
 "$()-:>E\`abcdefhilmnoprstuw×ÝáâäæéêñòóöđēĕħĮİĴ

Character set 2 (includes newline):
!'+,.0123456789<=@[]_qxz~

Since only set 1 contains non-ASCII characters, their UTF-8 bytes are also disjoint.
How it works

Program 1 is generally written with lambda expressions, spaces and parentheses, free use of builtin alphanumeric functions, and with the quine data as string literals at the end.

Program 1's own core code is turned into string literal data simply by surrounding it with quote marks.

To support this, every backslash is followed by a or b, which form valid escape sequences that roundtrip through show.
Another tiny benefit is that a, b and c are the only lower case letters whose ASCII codes are less than 100, saving a digit in the numerical encoding used by program 2.

The string literal encoding of program 2's core code is more obfuscated by using non-ASCII Unicode: Every character has 182 added to its code point to ensure there is no overlap with the original characters.

182 used to be 128, until I realized I could abuse the fact that 182 is twice the length of the string literal for program 1's code to shorten the decoding. (As a bonus, program 2 can use newlines.)

Program 2 is generally written with top level function equations (except for the final anonymous one), character literals and decimal numbers, list/range syntax and operators, and with the quine data as a list of lists of Ints at the end.

Program 1's core code is encoded as a list of its code points, with a final double quote.
Program 2's core code is encoded as the list of code points of the string literal used in program 1, still shifted upwards by 182.

Walkthrough, program 1

b and c are the values of the string literals for program 2 and 1, respectively, given as final arguments to the lambda expression. () is a dummy argument solely to satisfy PPCG's rule that the program should define a function.
foldr(\a->map pred)b(show()>>c) decodes the string b to the core code of program 2 by applying map pred to it a number of times equal to the length of show()>>c == c++c, or 182.
tail(show c) converts the string c to the core code of program 1, with a final double quote appended.
:pure b combines this in a list with the string b.
map(map fromEnum)$ converts the strings to lists of code points.
 `mappend`show(...) serializes the resulting list of lists and finally appends it to the core code of program 2.

Walkthrough, program 2

The toplevel z~z=[[['@','0'..]!!4..]!!z] is a function converting code points back to characters (necessary to write since not all the characters in toEnum are available.)

Its code point argument is also called z. The laziness marker ~ has no effect in this position but avoids a space character.
['@','0'..] is a backwards stepping list range starting at ASCII code 64, then jumping 16 down each step.
Applying !!4 to this gives a \NUL character.
Wrapping that in a [ ..] range gives a list of all characters, which !!z indexes.
The character is finally wrapped in a singleton list. This allows mapping the function z over lists using =<< instead of the unavailable map and <$>.

The toplevel q[x,q]_=z=<<x++q++[34,34]++x is a function constructing program 1 from the quine data list.

x is the data for the core of program 1 (including a final double quote) and the inner q is the obfuscated data for the core of program 2. _ is another dummy argument solely to make the final anonymous function a function instead of just a string.
x++q++[34,34]++x concatenates the pieces, including two double quote marks with ASCII code 34.
z=<< constructs program 1 by mapping z over the concatenation to convert from code points to characters.

The final q[[40,...]] is an anonymous function combining q with the quine data.

Jelly,  128 90 87 86 85 79 16 + 32 = 48 bytes
“OṾ⁾ọṙŒs”OṾ⁾ọṙŒs

Try it online!
79,7806,8318,7885,7769,338,115ỌṘ

Try it online!
The first program does the following:
“OṾ⁾ọṙŒs”OṾ⁾ọṙŒs
“OṾ⁾ọṙŒs”          String literal: 'OṾ⁾ọṙŒs'
         O         ord: [79, 7806, 8318,...]
          Ṿ        Uneval. Returns '79,7806,8318,7885,7769,338,115'
           ⁾ọṙ     Two character string literal: 'ọṙ'
              Œs   Swap case the two char literal: 'ỌṘ'.

This leaves the strings 79,7806,8318,7885,7769,338,115 and ỌṘ as the two arguments of the chain and they are implicitly concatenated and printed at the end.
The second program calculates the chr (Ọ) of the list of numbers which returns OṾ⁾ọṙŒs. Ṙ prints “OṾ⁾ọṙŒs” (with quotes) and returns the input, leaving “OṾ⁾ọṙŒs”OṾ⁾ọṙŒs as the full output.

Gol><>, 23 + 23 = 46 22 + 22 = 44 20 + 20 = 40 bytes
"lF{3+|3d*HqlJJJQpp2

Try it online!
'5ssTMMMotK-g6.6~Io

Try it online!
Verify it online!
How they work
"lF{3+|3d*HqlJJJQpp2

"..."        Push everything to the stack
 lF{3+|      Add 3 to everything on the stack
       3d*   Push 39 `'`
          H  Print everything on the stack (from the top) and halt

'5ssTMMMotK-g6.6~Io

'...'        Push everything to the stack
 5ss         Push 37 (34 `"` + 3)
    T    t   Loop indefinitely...
     MMMo      Decrement 3 times, pop and print
               At the end, `o` tries to print charcode -3, which is fishy (thanks Jo King)
               Program terminates

Adapted from Jo King's ><> answer. Having many more alternative commands for output and repeat, there was no need for g or p, and the two main bodies became much shorter.
Another main difference is that I generate the opponent's quote directly at the top of the stack. This way, it was slightly easier to keep the invariant of quote + my code + opponent code(reversed and shifted).


text:
Generalized matrix trace
Inspiration.
Given (by any means):

A two-argument (or single argument consisting of a two-element list) black box function, f: ℤ+ × ℤ+ → ℤ+ (input and output are 1, 2, 3,…)
A strictly positive integer matrix with at least two rows and two columns

return the matrix's function trace.
What is a function trace?
A normal matrix trace is the sum of the major diagonal (top-left to bottom-right) of a matrix:
[[1,2,3],[4,5,6],[7,8,9]] → [1,5,9] → 1+5+9 → 15
But instead of summing, we want to apply f along the diagonal:
[[1,2,3],[4,5,6],[7,8,9]] → [1,5,9] → f(f(1,5),9) or f(1,f(5,9))
Please state whether you use left-to-right or right-to-left.
The given matrix and all intermediate values will be strictly positive integers within your language's integer domain. The matrix may be non-square.
Examples
f(x,y) = xy, [[1,2,3],[4,5,6],[7,8,9]] → 1×5×9 → 45
f(x,y) = xy, [[1,2,3],[4,5,6],[7,8,9]] →  159 → 1
f(x,y) = x-y, [[4,5,6],[1,2,3]] → 4-2 → 2
f(x,y) = (x+y)⁄2, [[2,3,4],[5,6,7],[8,9,10]] → 5 or 7
f(x,y) = x+2y, [[1,2,3],[4,5,6],[7,8,9]] → 47 or 29
f(x,y) = max(x,y), [[1,2,3],[4,5,6],[7,8,9]] → max(1,5,9) → 9
f(x,y) = 2x, [[1,2,3],[4,5,6],[7,8,9]] → 2 or 4
f(x,y) = lcm(x,y), [[2,2,2],[2,2,3],[2,3,3],[4,4,4]] → lcm(2,2,3) → 6
Reference implementation.

What is the diagonal of [[2,2,2],[2,2,3],[2,3,3],[4,4,4]]?

@totallyhuman:[2,2,3]

Dammit, I read the title as "Generalized Matrix trance" and was sorely disappointed when the page loaded

R, 40 30 bytes
function(m,F)Reduce(F,diag(m))

Try it online!
Verify the test cases.
Traverses down the diagonal, so left-to-right in this case. For arithmetic operators, you can use "+" or backticks around the operators (+,*,-,%/%,^,%%)
Pretty straightforward: Reduce is R's equivalent to a fold, and the diagonal of a matrix is those elements a_ij where i==j, i.e., where the row and column indices are the same. diag has the appropriate behavior for non-square matrices.

Haskell, 39 bytes
Thanks @Laikoni for helping me fix the previously invalid solution!
f!m=foldl1 f[h|h:_<-zipWith drop[0..]m]

Associates to the left, try it online! (replace foldl1 by foldr1 for right-associative)

how about foldl1 f$zipWith(!!)m[0..]?

@proudhaskeller: That's what others tried already, but that fails on non-square matrices..

Mathematica, 16 bytes
-1 byte thanks to Martin Ender.
#~Tr~Fold[g]@*0&

Try it online!
Alternate solution, 17 bytes
Fold[g]@*Diagonal

Try it online!

17 bytes (black-box functions can be assumed under a given name)

That @*{} syntax doesn't make a lot of sense (you probably meant @*List), but the fact that it works anyway is pretty cool. In fact, it means you can replace the {} with a 0 and save a byte.

@MartinEnder I actually did have List first but I tried {} just for the heck of it and was extremely surprised that it worked. Makes sense but how does 0 work? o0

@totallyhuman The same way as {}. You're currently using {} as a function (or actually as a "head" using Mathematica terminology). If you used a generic f there, you'd get f[1,2,3] (if that's the diagonal). But with {} you get {}[1,2,3]. That's a completely meaningless expression, but heads can be arbitrary expressions themselves, and if Mathematica doesn't know what to do with them, it just leaves them as they are. Most of Mathematica's list manipulation functions actually work with expressions with an arbitrary head and in the case of Fold, the head is just ignored. [tbc]

So you can use 0 as the head instead, which gives 0[1,2,3] which is still meaningless, but works all the same.

@MartinEnder Ah, so I had misunderstood how it worked in the first place. Thanks!

It looks like you're not taking the function as input here.

@Shaggy First comment on this answer

Yeah, saw that after I commented. @Mr.Xcoder, I was going to ask if that's not in violation of our consensus that we cannot assume input to be assigned to a predefined variable but then I found this which directly contradicts that.

Clean, 56 bytes
t[[h:_]]f=h
t[[h]:_]f=h
t[[h:_]:r]f=f h(t[t\\[_:t]<-r]f)

Try it online! Folds from right-to-left.
[t\\[_:t]<-r] is the same as map tl r, but does not need import StdEnv.

Very elegant avoidance of StdEnv

Octave, 61 57 53 bytes
function m=g(f,m)for i=diag(m)'(2:end)m=f(m(1),i);end

Try it online!
Defines a function g which takes a function handle f and matrix m.
On the first iteration, m(1) returns the top-left matrix element; after that, it just returns m.

53 bytes

@Giuseppe That's what I did with my initial 61-byte version. Of course, I should've combined the strong points of my 57- and 61 byte version, which indeeds gives a 53 byte answer. Thanks for making me look at that again!

Husk, 7 bytes
Thanks @Zgarb for fixing my submission!
Ḟ₁§z!Tŀ

Associates to the left, Try it online! (for a right-associative version simply replace Ḟ by F)
Explanation
Unfortunately there's no easy way to get the diagonal of a matrix, so most the bytes are for that:
Ḟ₁§z!Tŀ  -- function ₁ is the function and matrix A implicit, example:
  §      -- fork A
     T   -- | transpose A: [[1,4,7],[2,5,8],[3,6,9]]
      ŀ  -- | enumerate A: [1,2,3]
   z!    -- and zipWith index: [1,5,9]
Ḟ₁       -- right fold function

Huh, built-in for anti-diagonals, but not for diagonals‽

@Adám I assume that's because you can compute antidiagonals of infinite matrices but not diagonals.

Haskell, 47 45 42 bytes
f%((h:t):r)|[]<-t*>r=h|x<-tail<$>r=f h$f%x

Try it online! Defines a function (%) which takes a function and a matrix as a list of lists as input.
The function is folds from right-to-left:
f % [[1,2,3], -> f 1 ( f % [[5,6],   -> f 1 ( f 5 ( f % [[9]] ) ) -> f 1 ( f 5 ( f 9 ) ) )
     [4,5,6],               [8,9]] )
     [7,8,9]]

f % ((h:t):r)              -- (h:t) is the first row and r the remaining rows
 | [] <- t *> r = h         -- a shorter way of checking wether t==[] or r==[]
 | x<-tail<$>r = f h $ f%x -- apply f to h and the result of recursively calling (%) on
                           -- the remaining matrix with the first column removed

Edit: -2 bytes thanks to BMO and -3 bytes thanks to Zgarb!

43 bytes by using $ and simplifying the conditional with *>.

@Zgarb Nice idea to use *>!

APL (Dyalog Unicode), 7 bytes (Adám's SBCS)
⎕/1 1⍉⎕

Try it online!
-3 thanks to a suggestion to convert this to a full program by Adám.
Right-to-left.

No need to use Adám's SBCS here: you could just use Dyalog Classic's.

@Zacharý The thing is that I'm answering in Dyalog Unicode, Classic is getting deprecated over time.

Not the codepage thoughm the codepage will live on

@Zacharý Well, let's rather be consistent. :P

JavaScript, 46 bytes
f=>a=>a.reduce((p,l,i)=>l[i]?f(p[0]|p,l[i]):p)

Thanks to @Shaggy, use bitwise or save one byte. That's magic.

g = f=>a=>a.reduce((p,l,i)=>l[i]?f(p[0]|p,l[i]):p)

c=()=>o.value=g(eval(`(x,y)=>${f.value}`))(m.value.split(/\n/g).map(x=>x.trim().split(/\s+/).filter(v=>v.length).map(v=>+v)).filter(x=>x.length))

a = <textarea id=m>1 2 3
4 5 6
7 8 9</textarea>

f = (x, y) => <input id=f type=text value="x + y" />

<button onclick=c()>Calc</button>

Result = <output id=o></output>

This doesn't seem to work if the matrix has more rows than columns.

@Shaggy so sad, 47 bytes now...

Yeah, that's what I had originally, too. Was just about to edit the fix into my solution but you beat me too it :( I think you can get one byte back, though, by using bitwise OR, though.

@Shaggy so magic

Forgot to mention: Apparently we can assume that black-box functions are assigned to a predefined variable so you could save 3 bytes if you wanted to take advantage of that.

Attache, 14 bytes
Fold#/Diagonal

Try it online! Set to f and call as f[function, array].
Explanation
This is a fork of two functions: Fold and /Diagonal. This, for arguments f and a, is equivalent to:
Fold[f, (/Diagonal)[f, a]]

/, when applied monadically to a function, returns a function that is applied to its last argument. So, this is equivalent to:
Fold[f, Diagonal[a]]

This folds the function f over the main diagonal of a.

A home-brewed language which is readable‽

@Adám ;D yes indeed!

AWK, 77 bytes
func z(F,M,r){for(e=1;e<M[1]&&e<M[2];)r=@F(r==""?M[1,1]:r,M[++e,e])
return r}

Try it online!
I was curious if AWK could do functional programming at all.  I think this counts.
The "Matrix" is defined as a standard associative array, with extra fields M[1]=#rows and M[2]=#columns. The function name is passed in as a string which is evaluated via the @F(...) syntax. Evaluation is performed left to right.
The r parameter is a placeholder to prevent overwriting an existing r variable and to avoid the need to reinitialize for each call. Typically extra space is added to designate such placeholders in AWK, but this is code golf, so every byte counts. :)
The TIO link implements all the test cases.

Haskell, 44 bytes
f#m=foldl1 f$zipWith(!!)m[0..length(m!!0)-1]

Try it online!

05AB1E, 15 10 bytes
Folds from right-to-left
Saved 5 bytes using a new built-in as suggested by Kevin Cruijssen
Å\`[.g#I.V

Explanation
Works the same as the old version, except that Å\ is a new built-in for pushing the main diagonal.
Try it online!
or as a Test Suite
Old Version
¬g£vyNè}[.g#I.V

Try it online!
or as a Test suite
Explanation
¬                 # get the head of the input (first row)
 g                # get its length (number of columns)
  £               # take that many rows from input
   v              # for each row_index, row (N,y) do:
    y             # push the row
     Nè           # get the nth element of the row
       }          # end loop
        [.g#      # loop until one value remain on the stack
            I.V   # run the input function

¬g£vyNè}[ can be Å\`[ now, saving 5 bytes.

Python 2, 61 bytes
lambda f,m:reduce(f,[l[i]for i,l in enumerate(m)if len(l)>i])

Try it online!
This works left-to-right.

@AsoneTuhid it can be any way, check the (x+y)⁄2 and x+2yexamples

Right, I misread, sorry

JavaScript (ES6), 58 56 bytes
g=(f,a,r=a[i=0][0],e=a[++i]&&a[i][i])=>e?g(f,a,f(r,e)):r

Folds left-to-right. Edit: Saved 2 bytes by using the fact that the array is strictly positive. Alternate solution, also 56 bytes:
(f,a,g=r=>(e=a[++i]&&a[i][i])?g(f(r,e)):r)=>g(a[i=0][0])

It doesn't look like you need the 1/ and you can save another 2 bytes by moving some stuff around: f=>a=>(h=r=>(e=a[++i]&&a[i][i])?h(f(r,e)):r)(a[i=0][0]). TIO

@Shaggy Oh, it's strictly positive, I hadn't seen that.

Apparently we can assume that black-box functions are assigned to a predefined variable so you could save 2 bytes if you want to take advantage of that.

@Shaggy Actually I think it would save 4 bytes (2x f,) off the first version?

You're right; sorry, forgot to count the f, when calling g again.

Java 8, 88 81 70 69 bytes
m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}finally{return;}}

Puts the result in the very first cell of the matrix instead of returning an integer (to save a byte).
Try it online.
Both folds [[1,2,3],[4,5,6],[7,8,9]] to f(f(1,5),9).
-7 bytes indirectly thanks to @KamilDrakari by using a similar trick as he did in his C# answer: instead of having a maximum boundary for the loop based on the rows/columns, simply try-catch the ArrayIndexOutOfBoundsException.
-11 bytes replacing catch(Exception e) with finally.
-1 byte thanks to @KamilDrakari again by putting the result in the very first cell.
Explanation:
m->{                   // Method with integer-matrix parameter and no return-type
  try{for(int i=1;     //  Start the index at 1 (0-based indexing)
          ;)           //   Loop indefinitely:
    m[0][0]=           //    Replace the value in the first cell with:
     f(m[0][0],        //     Call f with the current value of the first cell
       m[i][i++]));}   //     and the next diagonal cell as arguments
  finally{             //  If an ArrayIndexOutOfBoundsException occurred we're done,
    return;}}          //   in which case we'll terminate the method

Black box input format:
Assumes a named function int f(int x,int y) is present, which is allowed according to this meta answer.
I have an abstract class Test containing the default function f(x,y), as well as the lambda above:
abstract class Test{
  int f(int x,int y){
    return x+y;
  }

  public java.util.function.Consumer<int[][]> c =
    m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}finally{return;}}
  ;
}

For the test cases, I overwrite this function f. For example, the first test case is called like this:
int[][] inputMatrix = new int[][]{
  new int[]{1,2,3},
  new int[]{4,5,6},
  new int[]{7,8,9}
};
new Test(){
  @Override
  int f(int x,int y){
    return x*y;
  }
}.c.accept(inputMatrix);
System.out.println(inputMatrix[0][0]);

Standard ML (MLton), 59 bytes
fun t[h::_]f=h|t([h]::_)f=h|t((h::_)::r)f=f(h,t(map tl r)f)

Try it online! Folds from right-to-left.
Ungolfed:
fun trace [h::_]      f = h
  | trace ([h]::_)    f = h
  | trace ((h::_)::r) f = f (h, trace (map tl r) f)

Try it online!

tinylisp, 79 bytes
(load library
(d D(q((M)(i(h M)(c(h(h M))(D(map t(t M))))(
(q((F M)(foldl F(D M

The last line is an unnamed lambda function that takes a function and matrix and returns the matrix trace. The trace is left-associative (i.e. f(f(1,5),9)). Try it online!
Ungolfed
We define a helper function to compute the diagonal; then generalized-trace is merely a small wrapper around the library function foldl.
(load library)

(def diagonal
 (lambda (matrix)
  (if (head matrix)
   (cons
    (head (head matrix))
    (diagonal (map tail (tail matrix))))
   nil)))

(def generalized-trace
 (lambda (func matrix)
  (foldl func (diagonal matrix))))

When computing the diagonal recursively, we check whether (head matrix) is truthy. If the matrix is out of rows, it will be the empty list (nil), and head of nil is nil--falsey. Or, if the matrix is out of columns, its first row (head) will be the empty list (nil)--falsey. Otherwise, there will be a nonempty first row, which is truthy.
So, if the first row doesn't exist or is empty, we return nil. Otherwise, if there is a nonempty first row, we take (head (head matrix))--the first element of the first row--and cons (prepend) it to the result of the recursive call. The argument to the recursive call is (map tail (tail matrix))--that is, take all rows but the first, and take all but the first element of each row.

SNOBOL4 (CSNOBOL4), 86 bytes
T	I =1
	T =M<1,1>
I	I =I + 1
	T =EVAL(F '(T,M)')	:S(I)F(RETURN)
	DEFINE('T(M,F)')

Try it online!
Defines a function T (for TRACE) that takes an ARRAY and a string F that's the name of a function. Folds left-to-right.
Using indirect reference ($) doesn't work with functions. So using EVAL and passing a string to the name seems to be the only way to get a black-box function in SNOBOL.
Also, it's quite painful to define arrays; however, because invalid array references cause FAILURE, this works for non-square arrays -- if I is out-of-bounds in either dimension, the  F(RETURN) forces the function to return.
Edit:
Possibly, based on this meta post, I may assume that the black-box function F is defined under the name F, which would drop this to 75 bytes (remove use of EVAL and ,F in the function definition). However, I prefer this version since it's closer to passing a reference to a function.

Pari/GP, 42 bytes
f->a->fold(f,[a[i,i]|i<-[1..min(#a,#a~)]])

Try it online!

JavaScript, 61 57 56 52 50 44 42 bytes
Reduces left to right. Assumes the function is assigned to variable f, as per this meta post brought to my attention by Mr. Xcoder & totallyhuman. Can't say as I agree with it as it directly contradicts our existing consensus that we may not assume input is assigned to a pre-defined variable, but I'll take the few bytes saving for now.
a=>a.map((y,z)=>x=(n=y[z])?z?f(x,n):n:x)|x

Test Cases

g=
a=>a.map((y,z)=>x=(n=y[z])?z?f(x,n):n:x)|x
o.innerHTML=[[`f(x,y) = xy`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>x*y,45],[`f(x,y) = x<sup>y</sup>`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>x**y,1],[`f(x,y) = x-y`,[[4,5,6],[1,2,3]],(x,y)=>x-y,2],[`f(x,y) = <sup>(x+y)</sup>⁄<sub>2</sub>`,[[2,3,4],[5,6,7],[8,9,10]],(x,y)=>(x+y)/2,7],[`f(x,y) = x+2y`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>x+2*y,29],[`f(x,y) = max(x,y)`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>Math.max(x,y),9],[`f(x,y) = 2x`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>2*x,4],[`f(x,y) = lcm(x,y)`,[[2,2,2],[2,2,3],[2,3,3],[4,4,4]],(x,y)=>-~[...Array(x*y).keys()].find(z=>!(++z%x|z%y)),6]].map(([a,b,c,d],e)=>`Test #${++e}:  ${a}\nMatrix:   ${JSON.stringify(b)}\nFunction: ${f=c}\nResult:   ${g(b)}\nExpected: ${d}`).join`\n\n`

C, 76 bytes
i,t;f(g,A,n,m)int*A,(*g)();{for(t=*A,i=m+1;--n*--m;t=g(t,*A))A+=i;return t;}

Left-to-right.
Try it online!

Ruby, 55 53 bytes
->f,m,n=m[i=0][0]{(k=m[i+=1]&.[]i)?(n=f[n,k];redo):n}

Try it online!

C# (Visual C# Compiler), 72 69 60 bytes
m=>{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch{}}

Try it online!
try/catch allows the diagonal to be correctly reached by simply going along it and terminating when out of bounds.
3 bytes saved because, as pointed out by Kevin Cruijssen, black-box functions can be assumed to exist under a specific name.
9 bytes saved by returning via modifying an argument.
Thus, the function is called by storing the desired function under the name f, calling trace(matrix), and the result is stored in matrix[0][0].
Alternatively, if you really like verbosity,
C# (Visual C# Compiler), 97 + 13 = 110 78 69 bytes
(int[][]m)=>{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch{}}

Try it online!
32 bytes saved by using a predefined function, because not taking the function as a parameter allowed removing the System import and the long Func generic type.

Nice trick with the try-catch. I've been able to golf 7 bytes on my Java 8 answer (even though I have to use catch(Exception e) instead of catch. :) EDIT: Oh, been able to replace the catch(Exception e) with finally to save more bytes. Thanks again. +1 from me.

@KevinCruijssen you may also be able to benefit from my newest improvement (though I don't remember for sure whether Java is amenable to modifying arguments)

Thanks for letting me know. Although it is possible in Java, it means I'll have to change the finally into catch(Exception e), because I'm not returning inside the finally anymore. So m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch(Exception e){}} (73 bytes) is unfortunately longer for me in comparison to my current answer m->{int r=m[0][0],i=1;try{for(;;)r=f(r,m[i][i++]);}finally{return r;}} (70 bytes) But indeed a nice way to save bytes in your answer! :) Too bad I can only +1 your answer once.

APL NARS, 20 bytes, 10 chars
{⍺⍺/1 1⍉⍵}

test:
  f←{⍺⍺/1 1⍉⍵}
  ⎕←q←3 3⍴⍳10
1 2 3
4 5 6
7 8 9
  ×f q
45
  *f q
1
  {⍺+2×⍵}f q
47
  ⌈f q
9
  {2×⍺+0×⍵}f q
2
  -f ⊃(4 5 6)(1 2 3)
2
  {(⍺+⍵)÷2}f ⊃(2 3 4)(5 6 7)(8 9 10)
5
  ∧f ⊃(2 2 2)(2 2 3)(2 3 3)(4 4 4)
6

Good job. While I think you arrive to this on you own, it happens to be identical to Erik the Outgolfer's original solution.

Clojure, 30 bytes
#(reduce %2(map nth %(range)))

Reduces "from the left".

Jelly, 5 bytes
Left-to-right.
ŒDḢç/

Try it online!
Disclaimer: I do not know if this an acceptable input method for black-box functions. This assumes that the function is implemented in the link above, and is thus "named" (that is, it's callable with) ç, but otherwise I have no way to assign it to ç. If anyone has more experience with Jelly + black box functions, I would appreciate thoughts. After spending some time in chat, we figured that using ç might indeed be valid.

Husk, 6 bytes
F₁►L∂↔

Try it online!
takes function in the footer.
Folds from the left.

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:
Find Integral Roots of A Polynomial
Challenge
The challenge is to write a program that takes the coefficients of any n-degree polynomial equation as input and returns the integral values of x for which the equation holds true. The coefficients will be provided as input in the order of decreasing or increasing power. You can assume all the coefficients to be integers.
Input And Output
The input will be the coefficients of the equation in decreasing or increasing order of power.  The degree of the equation, i.e, maximum power of x, is always 1 less than the total no of elements in the input.
For example:
[1,2,3,4,5] -> represents x^4 + 2x^3 + 3x^2 + 4x + 5 = 0 (degree = 4, as there are 5 elements)
[4,0,0,3] -> represents 4x^3 + 3 = 0 (degree = 3, as there are 3+1 = 4 elements)

Your output should be only the distinct integral values of x which satisfy the given equation. All the input coefficients are integers and the input polynomial will not be a zero polynomial. If there is no solution for the given equation, then the output is undefined.
If an equation has repeated roots, display that particular root only once. You can output the values in any order. Also, assume that the input will contain at-least 2 numbers.
Examples
[1,5,6] -> (-3,-2)
[10,-42,8] -> (4)
[1,-2,0] -> (0,2)
[1, 1, -39, -121, -10, 168] -> (-4, -3, -2, 1, 7)
[1, 0, -13, 0, 36] -> (-3, -2, 2, 3)
[1,-5] -> (5)
[1,2,3] -> -

Note that the equation in the second example also has the root 0.2, but it is not displayed as 0.2 is not an integer.
Scoring
This is code-golf, so the shortest code (in bytes) wins!

Note: Before voting to close, please consider that this question is not a duplicate of this one. I can think of at least one approach to this problem which will not be trivially modifiable for the other challenge (although I'm not saying what; that's left to you ;P).

Can we assume we only need to return roots inside the integer bounds of our language? Or should the algorithm work even if the languages integer type range was increased, but the behaviour stayed the same.

Can we also use a native polynomial type if your language supports those?

You can only return roots inside the integer bounds of your language. And flawr, yes.

Are programs that run forever if there are no solutions accepted?

Yes, they are accepted

Why coefficients has to be integers?

That's to keep things simple.

MATL, 13 12 bytes
|stE:-GyZQ~)

Try it online!
This uses the fact that, for integer coefficients, the absolute value of any root is strictly less than the sum of absolute values of the coefficients.
Explanation
Consider input [1 5 6] as an example.
|    % Implicit input. Absolute value
     % STACK: [1 5 6]
s    % Sum
     % STACK: 12
t    % Duplicate
     % STACK: 12, 12
E    % Multiply by 2
     % STACK: 12, 24
:    % Range
     % STACK: 12, [1 2 ... 23 24]
-    % Subtract, elemet-wise
     % STACK: [11 10 ... -11 -12]
G    % Push input again
     % STACK: [11 10 ... -11 -12], [1 5 6]
y    % Duplicate from below
     % STACK: [11 10 ... -11 -12], [1 5 6], [11 10 ... -11 -12]
ZQ   % Polyval: values of polynomial at specified inputs
     % STACK: [11 10 ... -11 -12], [182 156 ... 72 90]
~    % Logical negation: turns nonzero into zero
     % STACK: [11 10 ... -11 -12], [0 0 ... 0] (contains 1 for roots)
)    % Index: uses second input as a mask for the first. Implicit display
     % STACK: [-3 -2]

As an alternative to Rouche's Theorem, the Rational Roots Theorem would also suffice to justify the bound you used. By the Rational Roots Theorem, all integer roots are bounded in absolute value by the maximum of the absolute values of the coefficients, a tighter bound than the sum. Or even tighter, by the absolute value of the "last" nonzero coefficient--i.e. the coefficient of the smallest power of x which has a nonzero coefficient. (Probably doesn't help save any bytes, just an alternative proof since the RRT is probably more familiar than Rouche to most folks.) :)

@mathmandan that approach is three bytes longer: Try it here, although I'm sure I've missed a trick or two

@Giuseppe Thanks to both. Maybe X>t_w&:GyZQ~), but still 13 bytes

... but I found a shorter alternative for the range

Haskell, 54 bytes
f l|t<-sum$abs<$>l=[i|i<-[-t..t],foldl1((+).(i*))l==0]

Try it online!
Brute force and synthetic division.
Ungolfed with UniHaskell and -XUnicodeSyntax
import UniHaskell

roots    ∷ Num a ⇒ [a] → [a]
roots xs = [r | r ← -bound … bound, foldl1 ((+) ∘ (r ×)) xs ≡ 0]
             where bound = sum $ abs § xs

Alternate solution, 44 bytes
Credit to nimi.
f l=[i|i<-[minBound..],foldl1((+).(i*))l==0]

Good luck with trying it online,  as this checks every number in an Int's range.

You can iterate i over [minBound..] and drop the whole t thing. Call f with explicit Int lists, e.g. f [1::Int,5,6]. Of course this doesn't finish in reasonable time.

@nimi Why would that ever stop? Wouldn't it infinitely loop?

No, Bounded types stop at maxBound, e.g. print [minBound::Bool ..].

Husk, 10 9 bytes
-1 byte thanks to Zgarb
uSȯf¬`Bṁṡ

Try it online!
Explanation
       ṁṡ   Concatenate together the symmetric ranges of each coefficient
            (It is guaranteed that the integer roots lie in the range [-n..n],
                        where n is the coefficient with the largest magnitude)
 Sȯf        Find all the values in that range which
    ¬       are zero
     `B     when plugged through the polynomial
            (Base conversion acts as polynomial evaluation)
u           De-duplicate the roots

You could do ṁṡ instead of oṡ►a if you deduplicate later.

@Zgarb Very nice! Thanks

Python 2 + numpy, 95 93 91 103 93 91 82 bytes
-2 bytes thanks to ovs
thanks Luis Mendo for the upper/lower bounds of the roots
-10 bytes thanks to Mr. Xcoder

from numpy import*
def f(r):s=sum(fabs(r));q=arange(-s,s);print q[polyval(r,q)==0]

Try it online!

91 bytes

@LuisMendo yes.

Our current consensus seems to be that programs must always terminate, unless the challenge states otherwise.

@Zgarb there, fixed!

Using numpy.polyval saves quite a few bytes

Wolfram Language (Mathematica), 50 47 42 25 27 bytes
{}⋃Select[x/.Solve[#~FromDigits~x==0],IntegerQ]&

Try it online!
Update: using Luis Mendo's fact, golfed off another 3 bytes
Pick[r=Range[s=-Tr@Abs@#,-s],#~FromDigits~r,0]&

Getting sloppier with the bounds, we can reduce this 5 more bytes per @Not a tree's suggestion:
Pick[r=Range[s=-#.#,-s],#~FromDigits~r,0]&

After posting this, OP commented allowing "native polynomials", so here's a 25 byte solution that accepts the polynomial as input.  This works because by default Mathematica factors polynomials over the integers, and any rational roots show up in a form like m*x+b that fails the pattern match.
Cases[Factor@#,b_+x:>-b]&

As @alephalpha pointed out this will fail for the case where zero is a root, so to fix that we can use the Optional symbol :
Cases[Factor@#,b_:0+x:>-b]&

This parses fine Mathematica 11.0.1 but fails and requires an extra set of parentheses around b_:0 in version 11.2.  This takes up back up to 27 bytes, plus two more after version 11.0.1. It looks like a "fix" was put in here
Try it Online!

I think you can use #.# instead of Tr@Abs@#: it's a worse bound but fewer bytes.

OP said in a comment that you could use your language's native polynomial type if one exists. I don't know Mathematica well but I imagine there is one... Would that save bytes?

It fails when 0 is a root.

@alephalpha, fixed.

24 bytes with a Default pattern and an operator right-composition

Wolfram Language (Mathematica), 33 26 31 bytes
Fixed an error noted by Kelly Lowder in the comments.
x/.{}⋃Solve[#==0,x,Integers]&

Try it online!
Previous incorrect solutions:
I just noticed that for no integer solution, the output is undefined instead of empty list; that allows to remove a few bytes.
x/.Solve[#==0,x,Integers]&

Try it online!
Now if no integer solution exists, the function returns x.
Previously:
x/.Solve[#==0,x,Integers]/.x->{}&

Try it online!

This fails as currently stated with 1,2,1 as it repeats the root and the OP said they had to be distinct. You need  Union to fix that.

@KellyLowder: Ah, I missed that. But then, it was also missing in the given test cases.

@KellyLowder: I've now fixed it. In case you downvoted because of this, can you please revert it?

@cellschk, yep done.

29 bytes by using an undocumented feature of Solve: the list of variables can be omitted.

R, 61 59 bytes
A special thanks to @mathmandan for pointing out my (incorrect) approach could be saved, and golfed!
function(p)(x=-(t=p[!!p][1]):t)[!outer(x,seq(p)-1,"^")%*%p]

Try it online!
Takes input as a list of coefficients in increasing order, i.e., c(-1,0,1) represents -1+0x+1x^2.
Using the rational root theorem, the following approach very nearly works, for 47 bytes:
function(p)(x=-p:p)[!outer(x,seq(p)-1,"^")%*%p]

Try it online!
-p:p generates a symmetric range (with a warning) using only the first element of p, a_0. By the Rational Root Theorem, all rational roots of P must be of the form p/q where p divides a_0 and q divides a_n (plus or minus). Hence, using just a_0 is sufficient for |a_0|>0, as for any q, |p/q|<=a_0. However, when a_0==0, as then any integer divides 0, and thus this fails.
However, mathmandan points out that really, in this case, this means that there's a constant factor of x^k that can be factored out, and, assuming k is maximal, we see that
P(x) = x^k(a_k + a_{k+1}x + ... a_n x^{n-k}) = x^k * Q(x)

We then apply the Rational Root Theorem to Q(x), and as a_k is guaranteed to be nonzero by the maximality of k, a_k provides a tidy bound for the integer roots of Q, and the roots of P are the roots of Q along with zero, so we will have all the integer roots of P by applying this method.
This is equivalent to finding the first nonzero coefficient of the polynomial, t=p[!!p][1] and using it instead of the naive p[1] as the bounds. Moreover, since the range -t:t always contains zero, applying P to this range would still give us zero as a root, if indeed it is.
ungolfed:
function(polynom) {
 bound <- polynom[polynom != 0][1]             #first nonzero value of polynom
 range <- -bound:bound                         #generates [-bound, ..., bound]
 powers <- outer(range,seq_along(p) - 1, "^")  #matrix where each row is [n^0,n^1,n^2,...,n^deg(p)]
 polyVals <- powers %*% polynom                #value of the polynomial @ each point in range
 return(range[polyVals == 0])                  #filter for zeros and return
}

(I think you could use the max of the absolute values instead of the sum; this wouldn't change the byte count, but it ought to improve performance.) Anyway, yes, pity the shorter version doesn't work with a_0==0. Is there some short way in R to search for the first (with powers ascending) nonzero coefficient, and use that instead? This would correspond to factoring out as many x's as possible first (of course, then you'd have to remember to output 0 also, which would presumably cost some bytes.)

@mathmandan max would be more efficient, but to your second point, as I don't have to worry about outputting 0 since it's generated by the range -t:t (where t is the first nonzero coefficient), it saves 2 bytes!

Oh, very nice! (And a beautiful explanation as well.)

Pari/GP, 31 bytes
p->[x-a|a<-factor(p)[,1],a'==1]

Factors the polynomial, and picks out the factors whose derivatives are 1.
Try it online!

Jelly, 8 bytes
ASŒRḅ@Ðḟ

Try it online! or as a test-suite!
How?

ASŒRḅ@Ðḟ || Full program (monadic link).

AS        || Sum the absolute values.
  ŒR      || And create the symmetric inclusive range from its negative value.
       Ðḟ || And discard those that yield a truthy value...
     ḅ@   || When plugging them into the polynomial (uses base convertion).

Based off Luis' answer. An alternative.

Is there something I'm missing about taking the (allowed) reverse order and doing Ær+.Ḟ?

I'm slightly confused since the Python answer with numpy isn't doing so either, and am thinking I've missed some edge case.

@JonathanAllan As I expected, yours fails for [1,2,3].

"If there is no solution for the given equation, then the output is undefined"

@JonathanAllan But it does fail for [10,-42,8], right?

I'm obviously not understanding something then.

@Jonathan You must return the integral roots of a given polynomial. 0 does not satisfy 10x^2+(-42)x+8=0, since 10*0^2+(-42)*0+8=8 is not equal to zero. Therefore, 0 is not a root of this polynomial.

ah, yes - 0.2 is a root so it fails.

C (gcc), 127 126 123 bytes

Saved one byte thanks to Kevin Cruijssen; golfing l+~j++ to l-++j.
Thanks to ceilingcat for saving three bytes.

x,X,j,m,p;f(A,l)int*A;{for(m=j=0;j<l;m+=abs(A[j++]));for(x=~m;X=x++<m;p||printf("%d,",x))for(p=j=0;j<l;X*=x)p+=A[l-++j]*X;}

Try it online!

Explanation
C (gcc), 517 bytes
x,X,j,m,p;                      // global integer variables
f(A,l)int*A;{                   // define function, takes in integer array pointer and length
 for(m=j=0;j<l;m+=abs(A[j++])); // loop through array, sum up absolute values
  for(x=~m;X=x++<m;             // loop through all values x in [-m, m], prime X
   p||printf("%d,",x))          // at loop's end, print x value if polynomial value is zero
    for(p=j=0;j<l;X*=x)         // loop through coefficients
     p+=A[l-++j]*X;}            // build polynomial

Try it online!

l+~j++ can be golfed to l-++j

@KevinCruijssen Thanks a lot.

@ceilingcat Thank you.

Octave, 59 49 bytes
@(p)(x=-(t=p(~~p)(end)):sign(t):t)(!polyval(p,x))

Try it online!
This is a port of my R answer. The only difference is that I have to explicitly use sign(t) and end to generate the range, and that it has polyval to compute the polynomial.
Takes input as a row vector of coefficients in decreasing order.

Java 8, 141 140 bytes
a->{int l=a.length,s=0,i,r,f,p;for(int n:a)s+=n<0?-n:n;for(r=~s;r++<s;System.out.print(p==0?r+",":""))for(p=i=0,f=1;i<l;f*=r)p+=a[l-++i]*f;}

Inspired by @Rod's Python 2 answer (his 82 bytes version).
Fun challenge! I certainly learned a lot of it when investigating about polynomials and seeing how some others here have done it.
Explanation:
Try it online.
a->{                   // Method with integer-array parameter and no return-type
  int l=a.length,      //  The length of the input-array
      s=0,             //  Sum-integer, starting at 0
      i,               //  Index integer
      r,               //  Range-integer
      f,               //  Factor-integer
      p;               //  Polynomial-integer
  for(int n:a)         //  Loop over the input-array
    s+=n<0?-n:n;       //   And sum their absolute values
  for(r=~s;r++<s;      //  Loop `r` from `-s` up to `s` (inclusive) (where `s` is the sum)
      System.out.print(p==0?r+",":""))
                       //    After every iteration: print the current `r` if `p` is 0
    for(p=i=0,         //   Reset `p` to 0
        f=1;           //   and `f` to 1
        i<l;           //   Loop over the input-array again, this time with index (`i`)
        f*=r)          //     After every iteration: multiply `f` with the current `r`
      p+=              //    Sum the Polynomial-integer `p` with:
         a[l-++i]      //     The value of the input at index `l-i-1`,
                 *f;}  //     multiplied with the current factor `f`

Python 2, 89 bytes
def f(a):s=sum(map(abs,a));return[n for n in range(-s,s)if reduce(lambda v,c:v*n+c,a)==0]

Try it online!

Octave with Symbolic Package, 63 bytes
@(p)(s=double(solve(poly2sym(p)==0)))(s==(t=real(s))&~mod(t,1))

Try it online!

05AB1E, 8 bytes
ÄOD(Ÿʒβ>

Try it online!

JavaScript (ES6), 97 bytes
a=>[...Array((n=Math.max(...a.map(Math.abs)))-~n)].map(_=>n--).filter(i=>!a.reduce((x,y)=>x*i+y))

Takes coefficients in decreasing order of power and outputs results in descending order.

Clean, 110 91 bytes
import StdEnv
?p#s=sum p
=[i\\i<-[~s..s]|i<>0&&sum[e*i^t\\t<-reverse(indexList p)&e<-p]==0]

Try it online!

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


text:
Tips for golfing in uBasic
UBASIC is a freeware basic interpreter written by Yuji Kida at Rikkyo University in Japan, specialized for mathematical computing. It is considered to be a "ready-to-run" language that and is capable of running on DOS and Windows.
What general tips do you have for golfing in uBasic? Any ideas that can be applied to code golf problems in general that are at least somewhat specific to uBasic. Please post one tip per answer.

Some helpful links
uBasic Wikipedia Page
Try it Online

Use ? in place of Print
Instead of using the Print command, ? may be used, as is the case in many BASIC languages - this means that the most simplest uBASIC Hello, World! program is as follows
0?"Hello, World!"

Rather than
10 Print "Hello, World!"

Try it Online!

Avoid Whitespace in For and Like statements
Whitespace between For and a variable name is not necessary in uBASIC meaning that a For loop may be condensed from
0 For t = 1 To 2
1 ?t
2 Next t

to
0Fort=1To2
1?t
1Nextt

Try it Online!

Execute multiple commands on a single line with :
uBasic allows for the execution of many commands on a single line with the use of : over a new line and new line number.
This means that this (50 Bytes)
0Fori=0To10
1Forj=1To9Step3
2?i*10+j
3Nextj
4Nexti

May be condensed to this (46 Bytes)
0Fori=0To10:Forj=1To9Step3:?i*10+j:Nextj:Nexti

Try it Online!

Use ; to Print Without a Newline
Much like is the case in VBA and other BASIC languages, you may add a ; to the end of a print statement to keep from printing a newline character and continue printing on that line.
Example:
0For i=1 To 10
1?i;
2Next i

Outputs
12345678910

Try it Online!
Similarly, , may be appended to the end of a print statement to prevent to pad the output right to a width of eight characters (note however, the output number or string must be of a length less than or equal to 6 characters)
Example
0?1,"|"

Outputs
1       |

Try it Online!


text:
Tips for golfing in Clean
What general tips do you have for golfing in Clean? Please post only ideas that can be applied to code golf problems in general, and are at least somewhat specific to Clean.
If you've never heard of Clean, you can find out more here.
Or, you can join the chat room.

Avoid import StdEnv when possible
To access built-in functions, even seemingly basic ones like (==) or map, an import statement is needed, usually import StdEnv because it imports the most common modules like StdInt, StdBool and so on (see here for more info on StdEnv).
However it can be possible to avoid this import for some challenges and just use the core language features like list comprehensions and pattern matching.
For example, instead of
import StdEnv
map f list

one can write
[f x\\x<-list]

List of alternatives:
Some functions or function invocations that need import StdEnv, an alternative that does not need the import and a rough estimate of bytes saved.

hd -> (\[h:_]=h), ~6 bytes
tl -> (\[_:t]=t), ~6 bytes
map f list -> [f x\\x<-list], ~10 bytes
filter p list -> [x\\x<-list|p x], ~11 bytes
(&&) -> %a b|a=b=a;%, ~6 bytes
(||) -> %a b|a=a=b;%, ~6 bytes
not -> %a|a=False=True;%, ~1 byte
and -> %[a:r]|a= %r=a;%_=True, ~0 bytes
or -> %[a:r]|a=a= %r;%_=False, ~0 bytes

The last few are unlikely to actually save bytes, because a direct replacement yields more bytes than the import, but it might be possible in cases where the recursion over the list is needed anyway.
This tip has successfully been used here.

Isn't import StdEnv + a and b (21 bytes) smaller than %[a:r]|a= %r=a;%_=True (22 bytes), though? Or would it be import StdEnv + a=True and b=True (31 bytes), in which case it's indeed definitely shorter? (I've never programmed in Clean, btw.)

@KevinCruijssen We were just discussing that in chat. It's true that those are unlikely to save bytes, except maybe when the program needs to recurse over a list anyway.

Know how to learn the language
After all, how can anyone golf in a language they can't use!
Online
Clean isn't a well-known or well-documented language, and the name certainly doesn't make it easy to find much-needed resources to remedy these issues... or does it?
Clean was originally called Concurrent Clean, which is still used in the preface of almost every document related to Clean - so if you're looking for Clean, look for Concurrent Clean instead.
One of Clean's more remarkable similarities to Haskell (of which there are many) is the existence of Cloogle, which is a function search-engine covering the libraries that Clean ships with.
Locally
The libraries that Clean ships with are in the form of decently-commented, somewhat self-documenting Clean source files, which are able to be browsed through using the IDE.
(It also comes with full example programs, under $INSTALL/Examples.)
Speaking of which, the Windows version of Clean comes with an IDE - while it is fairly limited by modern standards, it's worlds better than using a text editor and the command-line.
The two most useful features (in the context of learning) are:

You can double-click an error to see which line it's on
You can highlight a module name and press [Ctrl]+[D] to open the definition file (or use [Ctrl]+[I] for the implementation file), and toggle between the definition and implementation file with [Ctrl]+[/]

Forget about character encoding
Clean's compiler doesn't care about what encoding you think you've saved the source file as, just about the byte values in the file. This has some neat consequences.
In the body of the source code, only bytes with code-points corresponding to the printable ASCII characters are allowed, in addition to those for \t\r\n.
Literals:
In String and [Char] literals ("stuff" and ['stuff'] respectively), any bytes except 0 are allowed, with the caveat that " and ' must be escaped (for String and [Char] respectively), and that newlines and carraige returns must be replaced with \n and \r (also respectively).
In Char literals, any byte except 0 is permitted, meaning that:
'\n'

'
'

Are the same, but the second is one byte shorter.
Escaping:
Other than the standard letter escapes \t\r\n (etc.), all non-numeric escape sequences in Clean are either for the slash, or for the quote used to delimit the literal the escape is inside.
For numeric escape sequences, the number is treated as an octal value terminated after three digits. This means that if you want a null followed by the character 1 in a String, you need to use "\0001" (or "\0\61") and not "\01". However, if you follow the escape with anything but numbers, you can omit the leading zeroes.
Consequences:
This quirk with how Clean handles its source files allows String and ['Char'] to effectively become sequences of base-256 single-digit numbers - which has a multitude of uses for code-golf, such as storing indexes (up to 255, of course).

Name functions with symbols
When defining a function, it is often shorter to use some combination of !@$%^&*~-+=<:|>.?/\ than to use alphanumeric characters, because it allows you to omit white-space between identifiers.
For example: ?a=a^2 is shorter than f a=a^2, and invoking it is shorter as well.
However:
If the function identifier is used adjacent to other symbols, which can combine to form a different, but valid identifier, they will all be parsed as one identifier and you'll see an error.
For example: ?a+?b parses as ? a +? b
Additionally:
It is possible to overwrite imported identifiers in Clean, and so the only single-character symbol identifiers that aren't already used in StdEnv are @$?. Overwriting ^-+ (etc.) can be useful if you need more symbolic identifiers, but be wary that you don't overwrite one you're using.

Know your Knodes
Some of the strongest constructs (for golfing) in functional languages are let ... in ....
Clean of course, has this, and something better - the #.
What is a node?
Clean's #, and the ubiquitous | (pattern guard) are both known as 'node expressions'.
Notably, they allow you to program imperatively-ish in Clean (which is really good here!).
The # (let-before):
These both compute the value of an integer given as a string, multiplied by the sum of its chars
f s=let i=toInt s;n=sum[toInt c\\c<-:s]in n*i

f s#i=toInt s
#s=sum[toInt c\\c<-:s]
=s*i

Note how the version with # is shorter, and how we can redefine s. This is useful if we don't need the value that a variable has when we receive it, so we can just re-use the name. (let can run into issues when you do that)
But using let is easier when you need something like flip f = let g x y = f y x in g
The | (pattern guard):
Clean's pattern guard can be used like those in many other functional languages - however it can also be used like an imperative if ... else .... And a shorter version of the ternary expression.
For example, these all return the sign of an integer:
s n|n<>0|n>0=1= -1
=0

s n=if(n<>0)if(n>0)1(-1)0

s n|n>0=1|n<0= -1=0

Of course, the last one which uses the guard more traditionally is the shortest, but the first one shows that you can nest them (but only two unconditional return clauses can appear on the same line in layout rule), and the second shows what the first one does logically.
A note:
You can use these expressions basically anywhere. In lambdas, case ... of, let ... in, etc.

Use shorter lambdas
Sometimes you find yourself using a lambda expression (to pass to map, or sortBy, etc.). When you're doing this (writing lambdas), there's a bunch of ways you can do it.
The right way:
This is sortBy, with an idiomatic lambda sorting lists from longest to shortest
sortBy (\a b = length a > length b)

The other right way:
If you're using Data.Func, you can also do
sortBy (on (>) length)

The short way:
This is the same thing, but with a golfier syntax
sortBy(\a b=length a>length b)

The other way:
Using composition isn't shorter this time, but it can be shorter sometimes
sortBy(\a=(>)(length a)o length)

The other other way:
While it's a bit contrived here, you can use guards in lambdas
sortBy(\a b|length a>length b=True=False)

And also let-before node expressions
sortBy(\a b#l=length
=l a>l b)

A note:
There are two more forms of lambda, (\a b . ...) and (\a b -> ...), the latter of which is identical to the = variant, and the former of which exists for some reason and often looks like you're trying to access a property of something instead of defining a lambda so don't use it.

After seeing some of your golfed programs, I had got the impression \a=... was Clean's usual lambda syntax :P

You could also add the guards in lambda, as used here. This is undocumented (it even contradicts the language report), but works. Also, -> and = for lambdas are identical as far as the compiler is concerned (-> is old syntax). Only . is different (but I don't know exactly how).

And in this particular example you could consider using on(<)length, although the Data.Func import will break you up unless you need it already.

@Keelan Cool. I'll update this later today. I think you can also use let-before (#) in lambdas.

Yes, you can :-)

If you're using a String you should be using Text
Conversion to strings, and manipulation of strings (the {#Char} / String kind, not the [Char] kind) is quite lengthy and bad for golfing. The Text module remedies this.
Conversion:
Text defines the operator <+ for any two types which have toString defined.
This operator, used as a<+b is the same as toString a+++toString b - saving at least 19 bytes. Even if you include the extra import, ,Text, and use it only once, it still saves 14 bytes!
Manipulation:
Text defines a few string-manipulation staples that are missing from StdEnv:

The operator + for strings, which is much shorter than +++ (from StdEnv)
indexOf, with the C-like behaviour of returning -1 instead of Nothing on failure
concat, which concatenates a list of strings
join, which joins a list of strings using a separator string
split, which splits a string into a list of strings on a substring

Use Character List Literals
A character list literal is a shorthand way of writing something like ['h','e','l','l','o'] as ['hello'].
This isn't the limit of the notation, for example:

repeat'c' becomes ['c','c'..] becomes ['cc'..]
['z','y'..'a'] becomes ['zy'..'a']
['beginning']++[a,b,c]++['end'] becomes ['beginning',a,b,c,'end']
['prefix']++suffix becomes ['prefix':suffix]

These work in matching too:

['I don't care about the next character',_,'but I do care about these ones!']

Sometimes code is shorter
Clean has a bunch of really useful functions in the standard libraries, some of which are incredibly verbose to use without access to *World, and using *World in code-golf is generally a bad idea anyway.
To get around this problem, there are often ccalls you can use inside code blocks instead.
Some examples:
System Time
import System.Time,System._Unsafe
t=toInt(accUnsafe(time))

The above is 58 bytes, but you can save 17 bytes (down to 40+1) with:
t::!Int->Int
t _=code{ccall time "I:I"
}

Random Numbers
This one doesn't save bytes on its own, but avoids having to pass around a list from genRandInt
s::!Int->Int
s _=code{ccall time "I:I"ccall srand "I:I"
}
r::!Int->Int
r _=code{ccall rand "I:I"
}

Other Uses
In addition to these two, which are probably the main uses for this in code-golf, you can call any named function (including but not limited to every syscall), embed arbitrary assembly with instruction <byte>, and embed code for the ABC machine.


text:
Bottom part of the Hourglass
Challenge:
Input: Three integers: bottom-edge length; starting amount of grains of sand; index
Output: Output the state of the bottom part of an hourglass at the given index, based on the given bottom-edge length and amount of grains of sand.
Challenge rules:

We simulate the grains of sand with digits 1-9
We put the currently remaining amount of grains of sand at the top in the middle, following by a single character of your own choice (excluding digits, whitespaces and new-lines; i.e. -) on the line below it
When the hourglass is being filled, we fill it per row, one digit at a time
When the sand can go either left or right, we ALWAYS go right (the same applies to balancing the remaining amount of grains of sand above the hour glass)
When we've reached 9 it's filled, and we can't fit any more sand at that specific place in the hourglass
The amount of grains of sand left are also always rightly aligned
Once the bottom halve of the hourglass is completely filled, or the amounts of grains of sand left reaches 0, we can't go any further, and this would be the output for all indexes beyond this point
Both 0-indexed or 1-indexed is allowed, and please specify what you've used in your answer.
Trailing and leading spaces and a single trailing or leading new-line are optional
You are allowed to use any other character instead of a zero to fill up empty spaces of the bottom part of the hourglass (excluding digits, new-lines, or the character you've used as neck), if you choose to display them.
The bottom-edge length will always be odd
The bottom-edge length will be >= 3; and the amounts of grains of sand >= 0
If you want you are also allowed to print all states up to and including the given index
You can assume the (0-indexed) index will never be larger than the total amount of grains of sand (so when there are 100 grains of sand, index 100 is the maximum valid index-input).
The first index (0 for 0-indexed; 1 for 1-indexed) will output an empty hourglass with the amount of grains of sand above it.

Example: Pictures (or ascii-art) say more than a thousand words, so here is an example:
Input bottom-edge length: 5
Input amount of grains of sand: 100
Instead of a current index, I display all steps here:
Output for all possible indexes with bottom-edge length 5 and amount of grains of sand 100:
 100
  -
  0
 000
00000

  99
  -
  0
 000
00100

  98
  -
  0
 000
00110

  97
  -
  0
 000
01110

  96
  -
  0
 000
01111

  95
  -
  0
 000
11111

  94
  -
  0
 000
11211

  93
  -
  0
 000
11221

  92
  -
  0
 000
12221

  91
  -
  0
 000
12222

  90
  -
  0
 000
22222

  89
  -
  0
 000
22322

  88
  -
  0
 000
22332

  87
  -
  0
 000
23332

  86
  -
  0
 000
23333

  85
  -
  0
 000
33333

  84
  -
  0
 000
33433

  83
  -
  0
 000
33443

  82
  -
  0
 000
34443

  81
  -
  0
 000
34444

  80
  -
  0
 000
44444

  79
  -
  0
 000
44544

  78
  -
  0
 000
44554

  77
  -
  0
 000
45554

  76
  -
  0
 000
45555

  75
  -
  0
 000
55555

  74
  -
  0
 000
55655

  73
  -
  0
 000
55665

  72
  -
  0
 000
56665

  71
  -
  0
 000
56666

  70
  -
  0
 000
66666

  69
  -
  0
 000
66766

  68
  -
  0
 000
66776

  67
  -
  0
 000
67776

  66
  -
  0
 000
67777

  65
  -
  0
 000
77777

  64
  -
  0
 000
77877

  63
  -
  0
 000
77887

  62
  -
  0
 000
78887

  61
  -
  0
 000
78888

  60
  -
  0
 000
88888

  59
  -
  0
 000
88988

  58
  -
  0
 000
88998

  57
  -
  0
 000
89998

  56
  -
  0
 000
89999

  55
  -
  0
 000
99999

  54
  -
  0
 010
99999

  53
  -
  0
 011
99999

  52
  -
  0
 111
99999

  51
  -
  0
 121
99999

  50
  -
  0
 122
99999

  49
  0
 222
99999

  48
  -
  0
 232
99999

  47
  -
  0
 233
99999

  46
  -
  0
 333
99999

  45
  -
  0
 343
99999

  44
  -
  0
 344
99999

  43
  -
  0
 444
99999

  42
  -
  0
 454
99999

  41
  -
  0
 455
99999

  40
  -
  0
 555
99999

  39
  -
  0
 565
99999

  38
  -
  0
 566
99999

  37
  -
  0
 666
99999

  36
  -
  0
 676
99999

  35
  -
  0
 677
99999

  34
  -
  0
 777
99999

  33
  -
  0
 787
99999

  32
  -
  0
 788
99999

  31
  -
  0
 888
99999

  30
  -
  0
 898
99999

  29
  -
  0
 899
99999

  28
  -
  0
 999
99999

  27
  -
  1
 999
99999

  26
  -
  2
 999
99999

  25
  -
  3
 999
99999

  24
  -
  4
 999
99999

  23
  -
  5
 999
99999

  22
  -
  6
 999
99999

  21
  -
  7
 999
99999

  20
  -
  8
 999
99999

  19
  -
  9
 999
99999

So as example:
inputs: 5,100,1
output:
  99
  -
  0
 000
00100

Same example with another valid output format:
  99
  ~
  .
 ...
..1..

General rules:

This is code-golf, so shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters, full programs. Your call.
Default Loopholes are forbidden.
If possible, please add a link with a test for your code.
Also, please add an explanation if necessary.

Test cases:
INPUTS: bottom-edge length, amount of grains of sand, index (0-indexed)

inputs: 5,100,1
output:
  99
  -
  0
 000
00100

inputs: 5,100,24
output:
  76
  -
  0
 000
45555

inputs: 5,100,100
output:
  19
  -
  9
 999
99999

inputs: 5,10,15
output:
  0
  -
  0
 000
22222

inputs: 3,30,20
output:
 10
 -
 0
677

inputs: 3,3,0
 3
 -
 0
000

inputs: 9,250,100
   150
    -
    0
   000
  00000
 2333332
999999999

inputs: 9,225,220
    5
    -
    4
   999
  99999
 9999999
999999999

inputs: 13,1234567890,250
  1234567640
      -
      0
     000
    00000
   0000000
  344444443
 99999999999
9999999999999

inputs: 25,25,25
             0
             -
             0
            000
           00000
          0000000
         000000000
        00000000000
       0000000000000
      000000000000000
     00000000000000000
    0000000000000000000
   000000000000000000000
  00000000000000000000000
 1111111111111111111111111

For 5,100,10000 why does 20+9+9+9+9+9+9+9+9+9 = 101?

@Neil I'll change the rules a bit so the index can never go beyond the total sum. Probably better to understand.

Related

is the first input always an odd number?

@BrianH. "The bottom-edge length will always be odd" I realize I have a bit too much rules in this challenge, so I can understand you've read past it. :)

05AB1E, 68 63 59 57 56 bytes
IÅÉÅ9[DOO²Q#ćD_Piˆëć<¸«¸ì]ćā<ΣÉ}2äćR¸ì˜è¸ì¯ìJDSOIα'-‚ì.C

Try it online!
Explanation
IÅÉÅ9
We initialize the stack with a list of list of 9's.
Each list represents a row so the length of each list is odd and the length of the last list is equal to the first input.
An input of 5 would result in [[9], [9, 9, 9], [9, 9, 9, 9, 9]]
[DOO²Q#ćD_Piˆëć<¸«¸ì]
We then iterate over these lists decrementing elements in a list until the list consists only of zeroes, then moving on to the next. We stop when the total sum equals the second input.
[     #              ]   # loop until
 DOO                     # the sum of the list of lists
    ²Q                   # equals the second input
        ć                # extract the first list
         D_Pi            # if the product of the logical negation of all elements is true
             ˆ           # add the list to the global list
              ë          # else
               ć<        # extract the head and decrement it
                 ¸«      # append it to the list
                   ¸ì    # and prepend the list to the list of lists

Now we need to unsort the final list simulating removing elements from alternating sides instead of left-to-right as we have been doing.
ć                   # extract the row we need to sort
 ā<                 # push a list of indices of the elements [0 ... len(list)-1]
   ΣÉ}              # sort it by even-ness
      2äćR¸ì˜       # reverse the run of even numbers
                    # the resulting list will have 0 in the middle,
                      odd number increasing to the right and
                      even numbers increasing to the left
             è      # index into our final row with this
              ¸ì¯ì  # reattach all the rows to eachother

Now we format the output correctly
J              # join list of lists to list of strings
 DSOIα         # calculate the absolute difference of sum of our triangle and the 3rd input
      '-‚ì     # pair it with the string "-" and append to the list of rows
          .C   # join by newlines and center each row

Really? It was this complicated?

@MagicOctopusUrn: You are very welcome to outgolf me :) Some things about this method became a bit messy due to language quirks that I haven't found a better way around. Maybe there's a better way altogether? Maybe something more mathematical?

I was thinking about using binary numbers somehow... didn't think it out fully, didn't have a spare hour.

It has been awhile since I've tried to outgolf one of your solutions that's more than 20 bytes. Bit ashamed to admit it, but when I see your answers I usually don't waste the time trying to find improvements anymore; because usually I am unable to find any hah!

@MagicOctopusUrn: Too bad. You usually manage to come up with interesting alternatives (and/or improvements) to my solutions. Large programs in golfing languages are certainly more difficult to take the time to work on for sure.

You're slaying it recently, seriously I've been trying recently to find improvements on your newer answers and I think they're borderline optimized lol.

@KevinCruijssen: Explanation added.

Clean, 305 289 bytes
import StdEnv
@[h:t]|all((==)9)h|t>[]=[h: @t]=[h]
#s=length h/2
#m=hd(sort h)+1
=[updateAt(hd[e\\e<-flatten[[s+i,s-i]\\i<-[0..s]]|h!!e<m])m h:t]
$a b c=flatlines(map(cjustify(a+1))[fromString(fromInt(b-c)),['-']:reverse(map(map(toChar o(+)48))((iterate@[repeatn(a-r)0\\r<-[0,2..a]])!!c))])

Try it online!

@KevinCruijssen Fixed.

Perl 5, 301 bytes
($x,$t,$u)=<>;$s=$x;$t-=$g=$t>$u?$u:$t;while($s>0){@{$a[++$i]}=((0)x$s,($")x($x-$s));$a[$i][$_%$s]++for 0..($f=$g<$s*9?$g:$s*9)-1;$g-=$f;$s-=2}say$"x(($x-length($g+=$t))/2+.5),$g,$/,$"x($x/2),'-';while(@b=@{pop@a}){for($i=1;$i<@b;$i+=2){print$b[-$i]}print$b[0];for($i=1;$i<@b;$i+=2){print$b[$i]}say''}

Try it online!

Charcoal, 68 63 62 bytes
ＮθＮηＮζＦ⊘⊕θＦ⁹Ｆ⁻θ⊗ι«Ｊ⊘⎇﹪λ²⊕λ±λ±ι≔¬¬ζλ↑Ｉ⁺λＩＫＫ≧⁻λη≧⁻λζ»↑-Ｍ⊘⊖ＬＩη←Ｉη

Try it online! Link is to verbose version of code. Edit: Saved 5 bytes by removing the now-unnecessary index range check. Explanation:
ＮθＮηＮζ

Input the length into q, the number of grains of sand into h and the index into z.
Ｆ⊘⊕θＦ⁹Ｆ⁻θ⊗ι«

Loop over the (q+1)/2 rows (from bottom to top), then 9 grains in each cell in the row, then loop over the digits in the row.
Ｊ⊘⎇﹪λ²⊕λ±λ±ι

Jump to the digit.
≔¬¬ζλ↑Ｉ⁺λＩＫＫ≧⁻λη≧⁻λζ»

If possible, distribute a grain of sand to this digit, decrementing the amount of sand and index left. If we've passed the index, this still converts spaces to zeros, filling the hourglass. The digit is printed upwards because this means that the cursor will be on the neck after the last digit.
↑-

Print the neck.
Ｍ⊘⊖ＬＩη←Ｉη

Centre and print the amount of sand remaining.


text:
Create a scissors animation!
Try to create a simple ASCII art scissors animation!
Challenge
All inputs will be integers -31 through 31.
The output will be an animation (To be outputted somewhere, as long as the previous frame is replaced. GIFs are allowed.), separated by (approximately) 1 quarter of a second.
If the input (n) is positive:

The animation should start with 8<, AKA open scissors.
The next frame is 8=. This shows the scissors "cutting".
A dash (cut mark) is added behind the scissors, and the animation repeats until there are n dashes.

If the input is negative:

The scissors start open and facing towards the left (Like this: >8), with n spaces in front of it.
The scissors close and remain facing towards the left (=8).
The scissors re-open, as space is removed, and a dash is added behind the scissors.

If the input is zero:

Output just the scissors opening and closing, for 10 frames. They can be facing either direction, as long as it is consistent.

This is code-golf, so the shortest submission in bytes wins. (Even if your entry clearly won't win because of some sort of newfangled "golfing language", we'd still like to see it.)
Error messages are allowed, as long as the error message itself does not interfere with the animation.
Example Input and Output Pairs:
(I separated the frames for clarity, but there should be approximately .25 seconds between each frame)
Input: 1
Output:
8<
8=
-8<

Input: 2
Output:
8<
8=
-8<
-8=
--8<

Input: 5
Output:
8<
8=
-8<
-8=
--8<
--8=
---8<
---8=
----8<
----8=
-----8<

Input: 0
Output:
8<
8=
8<
8=
8<
8=
8<
8=
8<
8=

Input: -2
Output:
  >8
  =8
 >8-
 =8-
>8--

Input: -3
Output:
   >8
   =8
  >8-
  =8-
 >8--
 =8--
>8---

Enjoy!

Yes, it is. I will add that.

Does the font need to be monospaced?

@Οurous If your language supports it, yes. Otherwise, no.

SOGL V0.12, 53 bytes
LA0≠?.θ«IA}a∫H.¡*»:B┌* 8+Ƨ<=F2%W+a»b-@*+.0<?↔±}1¼UU░P

Try it Here!

MATL, 59 58 57 bytes
|EQG~10*+:"&FXx45@q2/kGg*XHY"8Vh61@oGO<Eq*+h4M?G|H-Z"hP]D

Try it at MATL Online! Or see an example run from the offline compiler:

It might just be me, but it appears that the closed scissor animations are longer than the open scissor ones. Is this just due to the processing of the language?

I haven't noticed that, but it could be. What I notice is, the leftward ones are a bit slower; and that makes sense because they have some more processing. Anyway, just to be sure, since the challenge says separated by (approximately) 1 quarter of a second I guess it's acceptable, right?

I found someone who knew MATL, and they showed my what your code was doing, and it seems fine :)

@iPhoenix I should have added an explanation:-)

JavaScript (ES2017) + HTML, 165 + 10 bytes
-16 bytes by @Shaggy
n=>(g=i=>i<-~(n?2*m:9)&&setTimeout(g,250,i+1,s=8+"<>="[i%2?2:n<0|0],o=("-".repeat(i/2)+s).padEnd(m+2),e.innerHTML=(n?n<0?[...o].reverse().join``:o:s)))(0,m=n<0?-n:n)

Try it in the below snippet:

let globalTimeout;
const _setTimeout = setTimeout;
window.setTimeout = function(){ globalTimeout = _setTimeout.apply(this, arguments); }
// Code above is to support user input

f=
n=>(g=i=>i<-~(n?2*m:9)&&setTimeout(g,250,i+1,s=8+"<>="[i%2?2:n<0|0],o=("-".repeat(i/2)+s).padEnd(m+2),e.textContent=(n?n<0?[...o].reverse().join``:o:s)))(0,m=n<0?-n:n)

// Code below is to support user input
f(10)
const $inp = document.getElementById("inp");
inp.addEventListener("change", ()=>{
  clearTimeout(globalTimeout);
  f(+inp.value);
});
<input type="number" id="inp" min="-31" max="31" value="10" />

A few quick savings to get you down to 157 bytes using just JS. (Although alerting each "frame" might not adhere to the spec, you may want to get clarification on that.)

@Shaggy Thanks for the improvements! I intentionally didn't use alert since the requirements are that the frames come at ~0.25s intervals, which alert wouldn't support without further user input.

Octave, 190 186 bytes
k=32+~e((a=abs(n=(z=input(''))+~z*10))+1,1);for i=1:a
clc
k(i:i+1)=[56,61-(s=sign(n))];q=@(m)fprintf(rot90([m ''],s));q(k)
if(i-a)pause(.25)
clc
k(i+1)+=s;q(k)
pause(.25);k(i)=45;end
end

Try it online! (note: clc does not work in TIO, so it's just all the animation frames outputted sequentially). Thanks for @LuisMendo for making me aware of the function e(...) in Octave, which is equal to exp(1)*ones(...).
It turns out that inline assignments return only the changed array entries, not the entire array. This means that constructions like q(k(i+1)+=s) are not possible, so the program is almost like MATLAB. In fact, the MATLAB entry is only slightly longer,
MATLAB, 198 195 bytes
n=input('');n=n+~n*10;a=abs(n);s=sign(n);k=zeros(a+1,1);q=@(k)fprintf(rot90([k ''],s));for i=1:a
k(i:i+1)=[56 61-s];clc
q(k)
if(i-a)pause(.25);
k(i+1)=k(i+1)+s;clc
q(k)
pause(.25)
k(i)=45;end
end

In Octave, I think you can replace +ones by the uglier +~e. Also, in Octave and in Matlab, replace [i i+1] by i:i+1.

@LuisMendo What on Earth is the use of e(...) like that? I don't think I've ever felt the need for an m-by-n matrix of e. Makes for good golfing though.

Perhaps the Octave developers had code golf in mind, haha

TI-BASIC, 173 bytes
:"-
:For(X,1,5
:Ans+Ans
:End
:For(X,1,32
:" "+Ans+" →Str1
:End
:ClrHome
:Input N
:N<0→X
:For(A,not(N),abs(N+5not(N
:For(B,4-3X,6-3X-(A=abs(N)),2
:33X-Anot(not(N
:Output(1,16,sub(Str1,33X+32,abs(Ans-1)-NX-31X)+sub(">8=8<8=",B,2)+sub(Str1,Ans+32,1
:rand(11
:End
:End

Having the 0 input terminate in a different frame from the others was a very interesting obstacle!
Since TI-BASIC doesn't like empty strings, this maintains at least one dummy character to the left of the scissors, the first of which is constantly a space; to hopefully avoid counting this as part of the n spaces for negative inputs, this program begins printing from the rightmost column of the first row, then wraps the remainder of the string downward in order to begin the actual field of animation there, fresh off the first column.
Some notes for an exotic device: TI-BASIC code size is measured in tokens, not characters. For consistent cross-calculator comparisons, we usually ignore byte counts dealing with header lengths (e.g., we subtract 8 from PROGRAM:SCISSORS). Additionally, for routines which are fully well-behaved on the home screen (those lacking in control structures, for the most part), we further eliminate the size of an empty program to "save" on 9 bytes as well. This program in particular is not typable on the home screen, so that liberty won't be taken.

I tried this challenge in TI-BASIC (In study hall, on my CE. Where else?) when I thought of it, and my program was at least twice as large as this. Well done.

PowerShell, 281 bytes
$n=$args[0];$o="8<";$c="8=";function x{sleep .25};if($n-le0){$n=[math]::abs($n);$o=">8";$c="=8";$p=' '*$n;$p+$o;$x;$p+$c;1..$n|%{$p=$p-replace"\s$","";$p+$o+('-'*$_);if($_-eq$n){break};$x;$p+$c+('-'*$_)};$x}else{$o;x;$c;1..$n|%{
$y='-'*$_;$y+"8<";if($n-eq$_){break};$x;$y+"8=";$x}}

Try it online!

Clean, 294 bytes
import StdEnv,System.Time,ArgEnv,System._Unsafe
Start#n=toInt(select(getCommandLine)1)
=[?k l\\k<-[1..]&l<-if(n==0)(flatten o$5)(init)[$(abs n+2)'\b'++if(n<0)(rjustify(abs n+2))reverse[c,'8': $i'-']\\i<-[0..abs n],c<-[if(n<0)'>''<','=']]]
?t#(Clock n)=accUnsafe clock
|n>t*250=id= ?t
$ =repeatn

Try it online!
Note that this doesn't work on TIO, the link is just for presentation purposes.
Your results may vary if you have a CLOCK_PER_TICK constant other than 1000, the default for x86 Windows Clean.

Python 2, 170 bytes
import time
n=input()
a=abs(n);s=a and n/a
for i in range([a-~a,10][a<1]):print'\n'*30+(a-i/2)*-s*' '+i/2*s*'-'+'>='[i%2]*(s<1)+'8'+'<='[i%2]*s+i/2*-s*'-';time.sleep(.25)

Try it online!

(approximately) 1 quarter of a second; why not use a sleep time of .2 seconds and save a byte?

Ruby,  169 bytes
->x{i="";o=?=;(x!=0&&x.abs*2+1||10).times{|l|o=o[?=]?x>0?"8<":">8":x>0?"8=":"=8";f=?\s*(x<0&&-x-l/2||0);system"cls";puts x>0?i+o:f+o+i;i+=?-if(l).odd?&&x!=0;sleep 0.25}}

Pretty much self explainatory when you dig into it, atleast in my opinion.
Program has to be running on a computer with the cls command/alias.
Try it online! ( Had to overwrite the system() method, just for this script, due to the limitations mentioned above. )
I did try to use
puts `cls`, ...

But it just printed an invisible character, anyone know why?

Stax, 46 41 bytes
üîφL↑≥ª⌡↨ÄA ¡`╢Σ·TmÄ↕=≈─Xí♫αF²M☻8]▒2±(═[3

Run and debug it
|, was included in a recent release, which is great for this challenge!
Uses JS requestAnimationFrame for pausing between snips.
Each testcase happens continuously after the other, so if you want a more clear version, try this!.
-5 bytes from recursive. (:R)
Explanation
c|a^5?rFxs0?.<={n'-*'8+s+x|a^^(x0<{:R}M{|,}9*|:pF
c|a^5? initial zero check:
     ? if the input is truthy
|a^  take abs(n) and increment
   5 otherwise push 5
r range 0..n-1
F for each value in the range,
xs0? r: if input is 0, then push 0, otherwise push loop iteration no.
.<={...Ffor each value in "<=",
n'_* repeat "_" r times
'8+ add 8 to that
s+ add current loop iteration to that
x|a^^ take abs(input) and increment twice
( pad on right to that length
x0<{...}M if input is less than 0
:R reflect the string (< → >)
{|,}9* delay 9 frames
|: output a form feed (clear screen)
p print the string without newline