text:
Element-wise string multiplication
Inspired by this challenge (thanks @cairdcoinheringaahing for the title!), your task is to take two printable ASCII strings and multiply them element-wise with the following rules.
How does it work?
Given two strings (for example split and isbn) you will first, truncate the longer one such that they have equal length and then determine their ASCII codes:
split -> spli -> [115, 112, 108, 105]
isbn  -> isbn -> [105, 115,  98, 110]

The next step will be to map them to the range [0..94] by subtracting 32 of each code:
[115, 112, 108, 105] -> [83, 80, 76, 73]
[105, 115,  98, 110] -> [73, 83, 66, 78]

Now you will multiply them element-wise modulo 95 (to stay in the printable range):
[83, 80, 76, 73] ⊗ [73, 83, 66, 78] -> [74, 85, 76, 89]

Add 32 to get back to the range [32..126]:
[74, 85, 76, 89] -> [106, 117, 108, 121]

And the final step is to map them back to ASCII characters:
[106, 117, 108, 121] -> "july"

Rules

You will write a program/function that implements the described steps on two strings and either prints or returns the resulting string
The input format is flexible: you can take two strings, a tuple of strings, list of strings etc.
The input may consist of one or two empty strings
The input will be characters in the printable range ([32..126])
The output is either printed to the console or you return a string
The output is allowed to have trailing whitespaces

Test cases
"isbn", "split"                  -> "july"
"", ""                           -> ""
"", "I don't matter"             -> ""
"             ", "Me neither :(" -> "             "
"but I do!", "!!!!!!!!!"         -> "but I do!"
'quotes', '""""""'               -> 'ck_iKg'
"wood", "hungry"                 -> "yarn"
"tray", "gzip"                   -> "jazz"
"industry", "bond"               -> "drop"
"public", "toll"                 -> "fall"
"roll", "dublin"                 -> "ball"
"GX!", "GX!"                     -> "!!!"
"4 lll 4", "4 lll 4"             -> "4 lll 4"
"M>>M", "M>>M"                   -> ">MM>"

Note: The quotes are just for readability, in the 6th test case I used ' instead of ".

Are you allowed to have trailing spaces in your output?

@EriktheOutgolfer Yes. Sorry, I added that after posting it.

Can we take an array of arrays of strings? abc, def -> [['a', 'b', 'c'], ['d', 'e', 'f']]

@totallyhuman I wouldn't say so. Though, if in your language strings are arrays of chars and chars have the same type as strings,  then it would be valid I guess.

Are we allowed to take input as a list of strings?

@Zacharý If you mean ["tray", "gzip"], yes. That's mentioned in the challenge.

MATL, 12 bytes
c32-p95\32+c

Try it online!
Explanation
c      % Implicitly input cell array of 2 strings. Convert to 2-row char matrix.
       % This pads the shorter string with spaces
32-    % Subtract 32, element-wise. Each char is interpreted as its ASCII code.
       % Note that padding spaces will give 0.
p      % Product of each column. Since (padding) spaces have been mapped to 0, the
       % product effectively eliminates those colums. So the effect is the same as
       % if string length had been limited by the shorter one
95\    % Modulo 95, element-wise
32+    % Add 32, element-wise
c      % Convert to char. Implicitly display

Clever way of managing the string length difference.

Jelly, 15 12 bytes
z⁶O_32P€‘ịØṖ

Try it online!
-3 thanks to Jonathan Allan.

Sneaky abuse of trailing whitespace. ;)

@Dennis Well it's in the rules, why not abuse it?

I believe you can save 3 bytes by using the niladic atom for printable characters, ØṖ, with z⁶O_32P€‘ịØṖ - you'd best double check that the arithmetic works though.

@JonathanAllan Of course.

Python 3, 80 74 71 bytes
lambda*t:''.join(map(lambda x,y:chr((ord(x)-32)*(ord(y)-32)%95+32),*t))

Thanks to @shooqie for golfing off 3 bytes!
Try it online!

71 if you take (s, t) as a tuple: lambda t:''.join(map(lambda x,y:chr((ord(x)-32)*(ord(y)-32)%95+32),*t))

Python 2, 75 70 bytes
-3 bytes thanks to Dennis' suggestion of shooqie's suggestion. -2 bytes thanks to Zacharý's suggestion.
lambda*l:''.join(chr((ord(i)-32)*(ord(j)-32)%95+32)for i,j in zip(*l))

Try it online!

Same trick that was suggested on my answer: lambda*t:''.join(chr(((ord(i)-32)*(ord(j)-32))%95+32)for i,j in zip(*t))

And same one that I suggested a lot: ((ord(i)-32)*(ord(j)-32))%95+32 => (ord(i)-32)*(ord(j)-32)%95+32 ...

o_o beating Dennis. +1

Eh, not really, I just changed to a list comprehension instead of using map. I was just slightly late.

Haskell, 60 57 bytes
zipWith(\a b->toEnum$f a*f b`mod`95+32)
f=(-32+).fromEnum

Try it online!
First line is an anonymous function taking two arguments.
This a straight forward implementation of the algorithm: zipWith takes both strings and applies a given function to the pairs of characters. It handles the truncation and also works for empty strings. fromEnum and toEnum are alternatives to ord and chr to switch between characters and their ASCII values which do not need a lengthy import.
Edit: -3 bytes thanks to Bruce Forte.

You can save 3 bytes by pulling out -32 and saving those parenthesis, see here.

C++, 331 291 282 270 268 bytes, Version 2 = 178 176 150 148 bytes
Original Version :
#include<string>
#include<algorithm>
#define L length()
#define S std::string
S m(S a,S b){S c;int m=a.L<b.L?a.L:b.L;auto l=[m](S&s){s=s.substr(0,m);std::for_each(s.begin(),s.end(),[](char&c){c-=32;});};l(a);l(b);for(int i=0;i<m;++i){c+=a[i]*b[i]%95+32;}return c;}

-40 bytes thanks to Bruce Forte
-39 bytes thanks to Zacharý
Version 2, inspired by other people's answers
#include<string>
#define L length()
using S=std::string;S m(S a,S b){S c;for(int i=0;i<(a.L<b.L?a.L:b.L);++i)c+=(a[i]-32)*(b[i]-32)%95+32;return c;}

If the first version uses a lambda, it's because i wanted to test C++11 std::async function i just learnt before, so i kept it for no reasons...
More readable version :
#include<iostream>
#include<string>
#include<algorithm>

using namespace std;

#define L length()
#define S string

//Function code for the original version
S m(S a,S b) {
    S c;
    int m = a.L < b.L ? a.L : b.L;

    auto l=[m](S&s){
        s = s.substr(0, m);
        for_each(s.begin(),s.end(),[](char&c){
            c -= 32;
        });
    };
    l(a);
    l(b);
    for(int i=0;i<m;++i) {
        c += a[i] * b[i] % 95 + 32;
    }
    return c;
}

//Code for the version 2
S m2(S a,S b) {
    S c;
    for(int i = 0; i < (a.L < b.L ? a.L : b.L); ++i) {
        c += (a[i] - 32) * (b[i] - 32) % 95 + 32;
    }
    return c;
}

int main() {
    string a, b, c;
    getline(cin, a);
    getline(cin, b);
    c = m(a, b);
    cout << c;
}

Welcome to PPCG!

Welcome to the site! Thanks for your answer, I appreciate it. I have no experience in golfing with C++, but here you'll find some tips. Enjoy your time here!

Also I'm pretty sure you can just submit a function, like this.

Can't you remove the spaces here: #include <string>=>#include<string> and #include <algorithm>=>#include<algorithm>?

In addition you should be able to create a macro equivalent to string and use it accordingly.

(a.L<b.L)=>a.L<b.L.

Also, on the second solution, is algorithm even needed? In addition, on the second solution, I don't think the braces are needed after the for loop.

Would it be possible to use using S=std::string; like I see you do in your more recent answers?

@Zacharý yeah, but it just saves one byte

(I think two if you remove the newline)

Dyalog APL, 36 34 33 25 24 bytes
{⎕UCS 32+95|×⌿32-⎕UCS↑⍵}

Try it online (TryAPL)!
Try it online (TIO)!
Input is a list of strings, and has trailing whitespace.
Here's how it works:
{⎕UCS 32+95|×⌿32-⎕UCS↑⍵}
                     ↑⍵ - the input as a 2d array
                 ⎕UCS   - codepoints
              32-       - subtract 32
            ×⌿          - element wise product reduction ([a,b]=>a×b)
         95|            - Modulo 95
      32+               - Add 32
 ⎕UCS                   - Unicode characters

I didn't get the interface of tryapl.org, so here's a TIO for those that want to try it.

There, I put both in there.

FSharp 275 bytes
let f (p : string, q : string) =
let l = if p.Length < q.Length then p.Length else q.Length
p.Substring(0,l).ToCharArray() |> Array.mapi (fun i x -> (((int(x) - 32) * (int(q.[i]) - 32)) % 95) + 32) |> Array.map (fun x -> char(x).ToString()) |> Array.fold(+) ""

Welcome to PPCG!

169 bytes

127 bytes

126 bytes

124 bytes

05AB1E, 16 15 bytes
.BÇ32-`*₃%32+çJ

Try it online!
-1 for Emigna pointing out ₃ pushes 95.

                 # ['hi', 'you']
.B               # [['hi ', 'you']]
  Ç              # [[[104, 105, 32], [121, 111, 117]]]
   32-           # [[[72, 73, 0], [89, 79, 85]]]
      `          # [[72, 73, 0], [89, 79, 85]]
       *         # [[6408, 5767, 0]]
        ₃%       # [[43, 67, 0]]
          32+    # [[75, 99, 32]]
             ç   # [['K', 'c', ' ']]
              J  # ['Kc ']

.BÇ32-`*95%žQsèJ

is another.

₃ saves a byte. Too bad about the empty string input. Otherwise ø would save a few more.

CJam, 23 bytes
{z{2' e]' f-:*95%' +}%}

Try it online!

C# (.NET Core),100 96 95 bytes
(l,n)=>{for(int i=0;i<l.Length&i<n.Length;)Console.Write((char)((l[i]-32)*(n[i++]-32)%95+32));}

Try it online!
-4 bytes thanks to @Zacharý
-1 byte by moving the increment
Uses a lambda and abuses the fact that characters are basically ints.

Can you use (l[i]-32)*(n[i]-32)%95+32?

Why yes, I can. Thanks!

You need to fully qualify the Console and you can use currying to save a byte. Compile to a Action<string, Action<string>> like l=>n=> and call like ("word")("string")

Mathematica, 114 bytes
(a=Min@StringLength[x={##}];FromCharacterCode[Mod[Times@@(#-32&/@ToCharacterCode/@(StringTake[#,a]&/@x)),95]+32])&

input

["public","toll"]

Is there a way to try it online?

of course, go to https://sandbox.open.wolframcloud.com/app/objects/ paste the code, paste input at the end, press shift+enter

what "8 chars"?

Sorry for the confusion! The message "Thanks!" would have been too short to post just like this, it needed 8 chars more.

ok....................................

Stacked, 52 bytes
[,:$#'"!MIN$take"![CS#.toarr]"!32-prod 95%32+#:''#`]

Try it online!
Function that takes two arguments from the stack.
Explanation
[,:$#'"!MIN$take"![CS#.toarr]"!32-prod 95%32+#:''#`]

Let's look at the first part, assuming the top two items are 'split' and 'isbn':
,:$#'"!MIN$take"!      stack:                      ('split' 'isbn')
,                      pair top two:               (('split' 'isbn'))
 :                     duplicate:                  (('split' 'isbn') ('split' 'isbn'))
  $#'                  length function literal:    (('split' 'isbn') ('split' 'isbn') $#')
    "!                 execute on each:            (('split' 'isbn') (5 4))
      MIN              obtain the minimum:         (('split' 'isbn') 4)
         $take         "take" function literal:    (('split' 'isbn') 4 $take)
                       (e.g. `'asdf' 2 take` is `'as'`)
              "!       vectorized binary each:     (('spli' 'isbn'))

This part performs the cropping.
Then:
[CS#.toarr]"!     stack: (('spli' 'isbn'))
[         ]"!     perform the inside on each string
                  string `'spli'`:
 CS               convert to a character string:    $'spli'
   #.             vectorized "ord":                 (115 112 108 105)
     toarr        convert to array:                 (115 112 108 105)
                  (needed for empty string, since `$'' #.` == `$''` not `()`

Then, the last part:
32-prod 95%32+#:''#`  stack: (((115 112 108 105) (105 115  98 110)))
32-                   subtract 32 from each character code:   (((83 80 76 73) (73 83 66 78)))
   prod               reduce multiplication over the array:   ((6059 6640 5016 5694))
        95%           modulus 95:                             ((74 85 76 89))
           32+        add 32:                                 ((106 117 108 121))
              #:      convert to characters:                  (('j' 'u' 'l' 'y'))
                ''#`  join:                                   ('july')

R, 88 bytes
function(r,s,u=utf8ToInt)intToUtf8((((u(r)-32)*(u(s)-32))%%95+32)[0:min(nchar(c(r,s)))])

anonymous function; takes input as two strings; third argument is just to ensure this is a one line function and save some bytes.
The TIO link below returns an array with entries named with the first input.
Try all test cases!

Perl 5, 65 bytes
64 bytes of code + -p flag.
$n=reverse<>;s/./($_=chop$n)&&chr 32+(-32+ord$&)*(-32+ord)%95/ge

Try it online!

D, 113 bytes
T m(T)(T a,T b){T c;for(int i;i<(a.length<b.length?a.length:b.length);++i)c~=(a[i]-32)*(b[i]-32)%95+32;return c;}

This is a port of HatsuPointerKun's C++ solution, don't forget to upvote them!
Try it online!

Java 8, 127 115 97 95 bytes
a->b->{for(int i=0;i<a.length&i<b.length;System.out.printf("%c",(a[i]-32)*(b[i++]-32)%95+32));}

Explanation:
Try it here.
a->b->{                       // Method with 2 char-array parameters and no return-type
  for(int i=0;                //  Index-integer, starting at 0
      i<a.length&i<b.length;  //  Loop over both arrays up to the smallest of the two
    System.out.printf("%c",   //   Print, as character:
      (a[i]-32)               //    Current char of `a` minus 32
      *(b[i++]-32)            //    multiplied with current char of `b` minus 32
      %95                     //    Take modulo-95 of that multiplied result
      +32));}                 //    And add 32 again

C#, 166 bytes
using System.Linq;s=>t=>{int e=s.Length,n=t.Length,l=e>n?n:e;return string.Concat(s.Substring(0,l).Select((c,i)=>(char)((((c-32)*(t.Substring(0,l)[i]-32))%95)+32)));}

I'm sure there's a lot of golfing to be done but I don't have time right now.
Try it online!
Full/Formatted Version:
using System;
using System.Linq;

class P
{
    static void Main()
    {
        Func<string, Func<string, string>> f = s => t =>
        {
            int e = s.Length, n = t.Length, l = e > n ? n : e;

            return string.Concat(s.Substring(0, l).Select((c, i) => (char)((((c - 32) * (t.Substring(0, l)[i] - 32)) % 95) + 32)));
        };

        Console.WriteLine(string.Concat(f("split")("isbn")));

        Console.ReadLine();
    }
}

I think (((c-32)*(t.Substring(0,l)[i]-32))%95)+32) can be ((c-32)*(t.Substring(0,l)[i]-32)%95+32) (might have screwed up the parens there ... it's looking like lisp!)

Python 2, 95 73 bytes

Thanks @Zacharý for 4 bytes: unwanted brackets removed

lambda x,y:''.join(chr((ord(i)-32)*(ord(j)-32)%95+32)for i,j in zip(x,y))

Try it online!

Goodness gracious ... learn to use order of operations!
(((ord(x[i])-32)*(ord(y[i])-32))%95)+32 => (ord(x[i])-32)*(ord(y[i])-32)%95+32

Common Lisp, 99 bytes
(lambda(a b)(map'string(lambda(x y)(code-char(+(mod(*(-(#1=char-code x)32)(-(#1#y)32))95)32)))a b))

Try it online!

Japt, 24 bytes
¬íVq)®®©c -HÃ×u95 +H dÃq

Returns a string with trailing null-chars (\u0000) when the first input is longer than the second.
Try it online! with the -Q flag to show formatted output, including the null-chars.
Run all the test cases using my WIP CodePen.

Perl 5, 95 bytes
@a=<>=~/(.)/g;@b=<>=~/(.)/g;$#a=$#b if@a>@b;print chr 32+(-32+ord$_)*(-32+ord$b[$i++])%95 for@a

Try it online!
Explanation:
@a=<>=~/(.)/g;@b=<>=~/(.)/g;  # Split the strings into 2 arrays
$#a=$#b if@a>@b;              # Truncate the first if longer than the second
print chr 32+(-32+ord$_)*(-32+ord$b[$i++])%95 for@a  # Multiply each character

I think you're not correctly truncating the result to the length of the smaller string (see here).

You're right.  Fixed it at a cost of many bytes

Charcoal, 30 bytes
Ｆ⌊⟦ＬθＬη⟧℅⁺³²﹪×⁻³²℅§θι⁻³²℅§ηι⁹⁵

Try it online! Link is to verbose version of code. I actually wrote the calcualation as (32 - ord(q)) * (32 - ord(h)) because it avoids consecutive numeric literals but I guess I could have just written (ord(q) - ord(" ")) * (ord(h) - ord(" ")) instead.

Pip, 19 bytes
(PA$* *(PA@?Zg)%95)

Takes the strings as command-line arguments. Try it online!
Explanation
(PA$* *(PA@?Zg)%95)
                     g is list of args; PA is string of all printable ASCII characters
            Zg       Zip items of g together: result is list of pairs of characters
        PA@?         Find index of each character in PA
       (      )      (Parentheses to get correct operator precedence)
   $* *              Map (fold on *) to the list: multiplies each pair of numbers
               %95   Take list items mod 95
(PA               )  Use those numbers to index into PA again
                     Print the resulting list of chars, concatenated together (implicit)

Factor, 45
[ [ [ 32 - ] bi@ * 95 mod 32 + ] "" 2map-as ]

It's a quotation (lambda), call it with two strings on the stack, leaves the new string on the stack.
As a word:
: s* ( s1 s2 -- ps ) [ [ 32 - ] bi@ * 95 mod 32 + ] "" 2map-as ;

"M>>M" "M>>M" s*      ! => ">MM>"
dup s*                ! => "M>>M"
dup s*                ! => ">MM>"
...

K (oK), 26 bytes
Solution:
`c$32+95!*/-32+(&/#:'x)$x:

Try it online!
Example:
`c$32+95!*/-32+(&/#:'x)$x:("split";"isbn")
"july"

Explanation:
Evaluation is performed right-to-left:
`c$32+95!*/-32+(&/#:'x)$x: / the solution
                        x: / assign input to variable x
                       $   / pad right to length on left
               (  #:'x)    / count each x (return length of each char list in list)
                &/         / min-over, get the minimum of these counts
           -32+            / subtract 32, this automagically converts chars -> ints
         */                / multiply-over, product of the two lists
      95!                  / modulo 95
   32+                     / add 32 back again
`c$                        / convert to character array

Kotlin, 65 bytes
{zip(it){a,b->(a-' ')*(b-' ')%95+32}.fold(""){s,i->s+i.toChar()}}

Try it online!

Factor, 39 bytes
[ [ [ 32 - ] bi@ * 95 mod 32 + ] 2map ]

Try it online!
Explanation:
This is a quotation (anonymous function) that takes two strings from the data stack and leaves one string on the data stack. In Factor, strings are just sequences of unicode code points and can be manipulated like any other sequence.

Assuming a data stack that looks like "split" "isbn" when this function is called...
[ [ 32 - ] bi@ * 95 mod 32 + ] push a quotation to the data stack (to be used later by 2map) "split" "isbn" [ [ 32 - ] bi@ * 95 mod 32 + ]
2map map over two sequences, combining them into one sequence with the given quotation which has stack effect ( x x -- x ).
At the beginning of the first iteration of 2map, the data stack looks like this: 115 105
[ 32 - ] push a quotation to the data stack to be used later by the word bi@. 115 105 [ 32 - ]
bi@ apply a quotation to the object on top of the data stack and the second-top object on the data stack 83 73
* multiply top two objects on the data stack 6059
95 push 95 to the data stack 6059 95
mod reduce NOS (next on stack) modulo TOS (top of stack) 74
32 push 32 to the data stack 74 32
+ add top two objects on the data stack 106
So, at the end of the quotation to 2map, we are left with 106, which is the code point for 'j', which is the first element of the output sequence. The quotation given to 2map will be run on each pair of elements until one of the two sequences no longer has any elements, meaning the output sequence will have the same size as the shorter of the two input sequences.

Red, 81 bytes
func[a b][repeat i min length? a length? b[prin a/:i - 32 *(b/:i - 32)% 95 + 32]]

Try it online!

Itr, 11 bytes
32â-R*95%+¥
Takes input as an array of 2 strings
prints additional trailing spaces if one string is longer
online interpreter
Explanation
32â-R*95%+¥ ; implicit input
32          ; constant 32
  â         ; push 32 below implicit input
   -        ; subtract 32 from input
    R*      ; multiply elements of input array
      95%   ; take input modulo 95
         +  ; add 32
          ¥ ; print value as string (implicit output will print '()' for empty string)

PHP, 112 bytes
for($i=0;$i<min(strlen($a=$argv[1]),strlen($b=$argv[2]));$i++)echo chr((ord($a[$i])-32)*(ord($b[$i])-32)%95+32);

109 bytes: for($i=0;$i<strlen($a=$argv[1])&&$i<strlen($b=$argv[2]);)echo chr((ord($a[$i])-32)*(ord($b[$i++])-32)%95+32); Also, I'm not entirely sure if replacing && with & might also be possible in PHP, reducing it by another byte to 108.

JavaScript (ES6), 89 bytes
Javascript and the curse of the lengthy function names ...
Using currying and the fact that charCodeAt returns NaN when called with an invalid position. There can be trailing nulls in the output.
a=>b=>a.replace(/./g,(c,i)=>String.fromCharCode((z=x=>x.charCodeAt(i)-32)(a)*z(b)%95+32))

Test

var f=
a=>b=>a.replace(/./g,(c,i)=>String.fromCharCode((z=x=>x.charCodeAt(i)-32)(a)*z(b)%95+32))

q=x=>'['+x+']'

;[["isbn", "split"],["", ""],["", "I don't matter"],["             ", "Me neither :("],
["but I do!", "!!!!!!!!!"],['quotes', '""""""'],["wood", "hungry"],["tray", "gzip"],
["industry", "bond"],["public", "toll"],["roll", "dublin"],["GX!", "GX!"],
["4 lll 4", "4 lll 4"],["M>>M", "M>>M"]]
.forEach(([a,b])=>console.log(q(a)+' x '+q(b)+' --> '+q(f(a)(b))))

Vyxal, 16 bytes
øŀC32-ƒ*95%32+Cṅ

Try it Online!
øŀC32-ƒ*95%32+Cṅ  # Example input: ["wood", "hungry"]
øŀ                # Align to left by padding to the right with spaces: ["wood  ", "hungry"]
  C               # Character codes: [[119, 111, 111, 100, 32, 32], [104, 117, 110, 103, 114, 121]]
   32-            # Subtract 32: [[87, 79, 79, 68, 0, 0], [72, 85, 78, 71, 82, 89]]
      ƒ*          # Element-wise multiply both: [6264, 6715, 6162, 4828, 0, 0]
        95%       # Modulo 95: [89, 65, 82, 78, 0, 0]
           32+    # Add 32: [121, 97, 114, 110, 32, 32]
              C   # From character codes: ["y", "a", "r", "n", " ", " "]
               ṅ  # Join together: "yarn  "

Ruby, 88 bytes
->a{c,d=a.map{_1[0,a.map(&:size).min].bytes}
c.map{((_1-32)*(d.shift-32)%95+32).chr}*""}

Attempt This Online!

Thunno 2 B, 12 bytes
Z32-€p95%32+

Try it online!
Explanation
Z32-€p95%32+  # Implicit input (converted to ordinals)
Z             # Zip them together (truncate longer one)
 32-          # Subtract 32 (vectorised)
    €p        # Product of each inner pair
      95%     # Modulo by 95 (vectorised)
         32+  # Add 32 (vectorised)
              # Implicit output (converted to string)

Zsh, 82 bytes
s=
repeat $#1 ((#2))&&s+=${(#)$((32+(#1-32)*(#2-32)%95))}&&1=${1:1} 2=${2:1}
<<<$s

Attempt This Online!
The flags needed to emulate zip() added too many characters, so we instead repeat for the length of the first argument, and check ((#2)) to see if we've reached the end of the second argument.

jq, 62 bytes
map(explode)|transpose|map((.[0]-32)*(.[1]-32)%95?+32)|implode

Attempt This Online!
transpose fills in null for missing elements, we suppress those with ?.

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:
Most efficient cubifier
Cubically is too tedious to manually write any code in. Your challenge is to translate ASCII text into Cubically source code.
Cubically
This is just a quick run-down of Cubically; the repository has a more complete guide and details.
Cubically is an esolang I wrote a while ago, designed to be painful to use. It contains two pieces of memory, a 3x3x3 Rubik's Cube and a register called the "notepad".
Memory
The internal Rubik's Cube is initialized like this:
   000
   000          top face
   000
111222333444    left, front, right, and back faces, respectively
111222333444
111222333444
   555
   555          down face
   555

After performing a clockwise 90° turn on the right face, the memory cube would look like this:
   002
   002
   002
111225333044
111225333044
111225333044
   554
   554
   554

Commands
A non-integer character sets the default command. For each integer before the default command is set once again, the command is performed with that integer. For example, x524y312 would perform command x with 5, then with 2, then with 4, then perform command y with 3, then with 1, then with 2.
The integers that commands use represent face indexes. So x0 would perform x on the UP (0-indexed) face. x1 would perform x on the LEFT (1-indexed) face, and so on.
Performing any command with 6 will perform that command on the notepad value. Performing any command with any integer over 6 will result in an error.
Here are some example commands:

R1 - turn the RIGHT face clockwise 90° so the internal cube will look like the second example above
R11 - turn the RIGHT face clockwise 90° twice, identical to R2
+0 - add all values of the UP face to the notepad
+000 - add all values of the UP face to the notepad three times
@6 - print the nonexistent 6th-indexed face (memory) as a character
%4 - print the sum of all values on the BACK face as an integer

A complete list of commands and syntax is available at the repository.
Challenge
You will take ASCII text as input and print a Cubically program as output.
Examples (stolen from here and here):
Input -> Output
Hello, World! -> +53@6+1F2L2+0@6L2F2U3R3F1L1+2@66L3F3R1U1B3+0@6:4U1R1+00@6-000@6*0-4+000@6-00@6+2-000000@6-5+4000@6-00@6/0+00@6:0+0/0+00@6
1$2$3$4$5$6$7$8$9$10$ -> B1+2/2%6@4+00/0%6@4+00/1%6@4+21/1%6@4+30/0%6@4+22/1%6@4+22/1%6@4+40/1%6@4+52/1%6@4+42/1%6@4

Rules

Your program may not contain a dictionary containing the translations for the 100 testcases.
Your program must finish in less than 180 seconds (no brute-force programs that take weeks).
Your program must output valid Cubically code that finishes in less than 180 seconds.
Your program will take input via standard input, unless you want to mess with the test driver.
Your program must output Cubically code that produces nothing but your program's input when run. ಠ_ಠ

Scoring
You will test your program with 100 pseudorandom strings of pseudorandom length. (A bash script is provided that will do this for you.) Here is how you will score:

Let the length of the output program be o.
Let the length of the input string be l.
Let a variable r be the result of o/l.
Find the average of all r: (r1 + r2 + r... + r100) / 100.

Test with this script. You'll have to modify it as instructed. Note that the program does not check whether the output is valid Cubically code.
If you can't get the script working, I can help. Ping me in the Cubically chat room.

Sandbox post

Would "@6 - print the sum of the nonexistent 6th-indexed face (notepad) as a character" be more accurate? Is %4 also a sum? Are + commands sum face then add that to all values or...?

@JonathanAllan @6/%6 just directly prints the notepad value as a character/integer. @x/%x (where x is any existing face) adds all values on the x-indexed face and prints the sum as a character/integer. + adds all the values on the specified face to the register.

Ah, for some reason I was thinking of the notepad as having 9 values too.

C++11, Score: 6.37
#include <iostream>
#include <vector>
#include <array>
#include <limits>
#include <algorithm>

const int inf = std::numeric_limits<int>::max(),
maxDiff = 128, nFace = 6;
std::array<int, maxDiff+1> plusvalue, totalvalue, plustrace, totaltrace;
std::array<int, nFace> input;

void prtrace(int value) {
    while (value) {
        std::cout << plustrace[value];
        value -= input[plustrace[value]];
    }
}

void prexpr(int i) {
    char xorwt = 0;
    if (i < 0) {
        xorwt = '+' ^ '-';
        i = -i;
    }
    if (totalvalue[i] != 0 && totalvalue[i] != inf) {
        std::cout << (char)('+' xor xorwt);
        prtrace(totaltrace[i]);
        if (totaltrace[i] != i) {
            std::cout << (char)('-' xor xorwt);
            prtrace(totaltrace[i] - i);
        }
    }
}

int main() {
    std::cout << "RU";
    input = {6, 15, 27, 26, 19, 42};
    std::cin >> std::noskipws;

    std::fill(plusvalue.begin(), plusvalue.end(), inf);
    plusvalue[0] = 1; // '+'
    for (int i = 0; i < nFace; ++i) { // knapsack, each value repeated inf times
        int val = input[i];
        if (val == 0) continue;
        for (int p = 0; p <= maxDiff - val; ++p) {
            if (plusvalue[p] != inf && plusvalue[p + val] > plusvalue[p] + 1) {
                plusvalue[p + val] = plusvalue[p] + 1;
                plustrace[p + val] = i;
            }
        }
    }
    for (int p = 0; p <= maxDiff; ++p) totalvalue[p] = plusvalue[p], totaltrace[p] = p;
    totalvalue[0] = 0;
    for (int sub = 1; sub <= maxDiff; ++sub) {
        if (plusvalue[sub] == inf) continue;
        for (int p = 0; p <= maxDiff - sub; ++p) {
            if (plusvalue[p+sub] != inf && totalvalue[p] > plusvalue[p+sub] + plusvalue[sub]) { // include '+'s
                totalvalue[p] = plusvalue[p+sub] + plusvalue[sub];
                totaltrace[p] = p+sub;
            }
        }
    }

//    // Note: plustrace[x] = i<=nFace : plustrace[x-input[i]] + 1 = plustrace[x]
//    long long sum = 0;
//    for (int i = 0; i <= maxDiff; ++i) {
//        sum += totalvalue[i];
//        std::cout << i << '\t' << totalvalue[i] << '\t';
//        prexpr(i);
//        std::cout << '\n';
//    }
//
//    std::cout << "_______________________________\n\nAverage = " << sum / (maxDiff + 1.) << '\n';

// RU 3.98131

    char ch;
    int cur = 0;
    while (std::cin >> ch) {
        int diff = ch - cur;
        prexpr(diff);
        std::cout << "@6";
        cur += diff; // cur = ch
    }
}

/*
RU 3.98131
*/

Try it online! (generate Cubically code from ASCII) and (run Cubically code)
Explanation:

First the program prints "RU", which make the face sum from {0,9,18,27,36,45} to {6, 15, 27, 26, 19, 42}. What makes that face sum set useful is that the gcd is 1, so by Bézout's identity there exist a way to construct any number d from a sum (or difference) of those numbers.
Therefore, if the next char is ch and the current notepad value is n, then let d = ch - n, we can execute Cubically commands in the form +{digits from 0 to 5}-{digits from 0 to 5} such that the notepad value becomes ch. Then just execute %6 to print notepad value.
To find the most efficient way to express d as a sum/difference of numbers in the face sum set, I use Knapsack algorithm for all numbers from 0 to 128. E.g., for d=1, the program gets 27 - 26 = 1, so it prints +2-3, which is 27 - 26 = 1. Which can be seen when run the program with input abc, the program output

RU+4333@6+2-3@6+2-3@6

Woah, great job! The Knapsack algorithm is what we were looking for I guess.

Note that due to language updates, you can get a better score via calling @ implicitly - @6 can be shortened to @ in all cases.

Lua, Score: 85.91 13.50 13.20 12.70 9.41 9.32 9.83 9.66 9.12 9.06 8.03 (Average)
-- Get input
local inp = io.read("*a")

local out = ""
local faces = { [5] = 45, [4] = 36, [3] = 27, [2] = 18, [1] = 9 }
local lastChar = nil

-- Mode the program is in
-- 2 = not set (needs :), 1 = just set (needs +), 0 = normal
local mode = 1;
for i = 1, inp:len() do
  -- Character value at current position
  local c = string.byte(inp, i)

  if c == lastChar then
    -- Repeat character
    out = out .. "6"
  elseif c % 9 == 0 and c <= 45 then
    if #out == 0 then
      out = out .. "@"
    end
    out = out .. (c / 9)
  else
    local c2 = c

    -- Handle if difference from lastChar is divisible by 9
    if lastChar and (c - lastChar) % 9 == 0 then
      local difference = c - lastChar
      if difference > 0 then
        out = out .. "+"
      else
        out = out .. "-"
        difference = difference * -1
      end

      for index = 5, 1, -1 do
        local face = faces[index]
        while difference >= face do
          difference = difference - face
          out = out .. index
        end
      end
      c = 0
    end

    -- Handle anything not divisible by 9
    local extra = c % 9
    if extra > 0 then
      -- Try to optimize by dividing by 9, if possible
      if lastChar and math.floor(lastChar / 9) == extra then
        out = out .. "/1"
        mode = 1
        extra = 0
      else
        while extra > 0 do
          local n = extra > 5 and 5 or extra

          if mode == 2 then
            out = out .. ":"
            mode = 1
          elseif mode == 1 then
            out = out .. "+"
            mode = 0
          end
          out = out .. n
          extra = extra - n
        end
        out = out .. "/1"
        mode = 1
      end

      c = c - (c % 9)
    end

    -- Handle anything divisible by 9
    for index = 5, 1, -1 do
      local face = faces[index]
      while c >= face do
        if mode == 2 then
          out = out .. ":"
          mode = 1
        elseif mode == 1 then
          out = out .. "+"
          mode = 0
        end
        c = c - face
        out = out .. index
      end
    end

    out = out .. "@6"
    lastChar = c2
  end

  mode = 2
end
print(out)

Try it online!
Okay, I don't think I can optimize this anymore.
This version iterates through each character, adding c % 9 (where c is the character's decimal value) by doing :5+2/1, then adds the parts divisible by 9 by adding that face's value. For example: :2/1+551@ to print "e", where :2/1 adds 2, +551 adds 99 (9 * (5 + 5 + 1), or 9 * 11), and @ prints the output. Input is read with io.read().
Optimizations include directly adding/subtracting after printing if the difference between characters is a multiple of 9, dividing the current value if possible rather than setting c % 9 from scratch, and repeating characters by printing the current value again rather than recalculating it. Additionally, I've implemented Kamil's method of instantly printing any face that already contains the target value, and MD XF's suggestion to not use : at the beginning, but instead just start with a +.

I actually feel kinda bad for posting a few minutes faster than this much better answer...

@KamilDrakari Oh hey, I can comment now! No worries. Your answer is much cleaner than mine anyway.

You can always comment on your own questions and answers, but you're not quite to general comment privileges yet. Shouldn't be long with answers like this (or, more likely, just this answer once a few more people see it)

@KamilDrakari Oh I see, thanks.

Good job to both of you, and great first answer, TehPers! @KamilDrakari, if you'd like to request that Magic Octopus Urn awards the bounty to this answer instead, I can let him know. (It's your choice; you won the bounty)

@MDXF I'm not quite that nice :P

Holy wow, you're still improving this?!?

@MDXF I noticed that the "c % 9" bit could be shortened. Regardless, Kamil's new answer is a lot more fun since it actually rotates the faces.

Something you can optimize is printing more than one of the same character. For example, @6@6@6@6@6 to @66666

@MDXF Oh, good idea! I'll add that now real quickly

Also, this doesn't work for multiple-line inputs. For example, with the input This is a test<newline>Tests are the best, your code will output this.

@MDXF The main issue is that my two options are io.read(), which reads whatever happens to be input (generally by the user), and f = io.open("str.txt") inp = f:read("*a") f:close(), which only works because you save to a text file, but also gives an extra newline of input (which does work). I can switch back to reading from the filesystem if you want. It only prints the first line for you because it seems to provide input twice, once per line, for that test.

You can change local inp = io.read() to local inp = io.read("*all"). That fixes the problem.

Another possible optimization - since the notepad starts at 0, you don't actually need to output, e.g. :5+124, instead you can just write +5124, which will probably get the score down a little bit if you tweak it right.

You'll likely get a better score if you change your answer to support some of the recent Cubically updates, such as implicit face turns.

Note that due to language updates, you can get a better score via calling @ implicitly - @6 can be shortened to @ in all cases.

It appears this is broken right now; it often prints 5.0 in seemingly random places, and the output is wrong. I can't paste the TIO link here as it is too long, but I'll send it in the Cubically chatroom.

Cubically, Score: 86.98
U3D1R3L1F3B1U1D3~:7+1(-1@3(-1%1)6:1+3111@6%1-31111+004@6:1+11111%6:1+45@6:1-1%6~:7+1)6

Try it online!
Turns out, all you need is conditional loops, a face equal to 1, and consistent End-Of-Input behavior.
U3D1R3L1F3B1U1D3     set LEFT face sum to 1
~:7                  read input, set notepad to input
+1                   add 1 to notepad

(                    open loop that can always be jumped to
 -1                   subtract 1 from notepad
 @3                   print RIGHT face (ASCII 43 '+')

            ##   the following mechanism gets the output program's   ##
            ##   notepad to the current inputted ASCII value:        ##

 (                    open loop that can always be jumped to
  -1                   subtract 1 from notepad
  %1                   print '1'
 )6                   jump back to loop while notepad is nonzero

            ##   the following mechanism prints "/1@6:1"             ##

 :1+3111@6            set notepad to 47,    print (ASCII 47 '/')
 %1                   print LEFT face       print (integer '1')
 -31111+004@6         set notepad to 64,    print (ASCII 64 '@')
 :1+11111%6           set notepad to 6,     print (integer 6)
 :1+45@6              set notepad to 58,    print (ASCII 58 ':')
 :1-1%6               set notepad to 0,     print (integer 1)

 ~                    read input
 :7+1                 set notepad to input plus 1, so EOF changes to zero
)6                    loop if notepad is truthy

The adding/subtracting of the LEFT face is to get the loop to end when EOF is read.

You have got to be kidding. This is incredible.

Oh hey, it even has a better score than my original C# answer!

Note that due to language updates, you can get a better score via calling @ implicitly - @6 can be shortened to @ in all cases.

C# (.NET Core), Score: 129.98 11.73 10.82 9.62 10.33 10.32 10.20
-1.2 point from MD XF's suggestion to use @6666... instead of @6@6@6@6... for repeating character, and superior initialization sequence
static void Main()
{
	List<byte> input = new List<byte>();
            int inChar = Console.Read();
            while (inChar != -1)
            {
                input.Add((byte)inChar);
                inChar = Console.Read();
            }

            Console.Write("U3D1R3L1F3B1U1D3");
            byte[] sides = new byte[] { 20, 1, 14, 43, 24, 33 };

            byte currentChar = 0;

   	    if(currentChar == input[0] || sides.Contains(input[0])) Console.Write("@");

            foreach (byte character in input)
            {
		if (currentChar == character)
		{
			Console.Write("6");
			continue;
		}

		if (sides.Contains(character))
		{
			Console.Write(Array.IndexOf(sides, character));
			continue;
		}
                if (currentChar < character)
                {
                    Console.Write("+");
                    while (currentChar < character)
                    {
                        byte nextAdd = sides.Where(s => s + currentChar <= character).Max();
                        currentChar = (byte)(currentChar + nextAdd);
                        Console.Write(Array.IndexOf(sides, nextAdd));
                    }
                }

                if (currentChar > character)
                {
                    Console.Write("-");
                    while (currentChar > character)
                    {
                        byte nextSub = sides.Where(v => currentChar - v >= character).Max();
                        currentChar = (byte)(currentChar - nextSub);
                        Console.Write(Array.IndexOf(sides, nextSub));
                    }
                }

                Console.Write("@6");
            }
}

Try it online!
My newest version actually does some manipulation of the cube! Yay!
That first Console.Write up there is a fixed manipulation MD XF worked out that creates this cube:
   242
   202
   242
000131555313
010121535343
000131555313
   424
   454
   424

The significance of this cube is that one of its sides has a sum of 1, allowing manipulations of the Notepad on a smaller scale than multiples of nine, and in particular it simplifies relative movement rather than needing to start from zero each character; in this algorithm both addition and subtraction are used to take the shortest path between characters.
MD XF's version of the initialization causes side 2 to have a sum of 14, which saves many bytes of output for ASCII distances between 14 and 20.
Now can handle inputs with internal newlines, Console.Read() gets individual characters until End of File; see the TIO link which should have the input
Hello,
World!

Shaved a couple fractions of a point by immediately outputting a character if its ASCII value just happens to already exist on a side.
Test Script courtesy of MDXF

Previous submission here and explanation:
This is kinda boring, but as far as I can tell it works. Admittedly I only tried Hello, World! but I ran the output in the TIO Cubically interpreter and it output "Hello, World!" so I assumed it works.
Rather than actually manipulating the cube at all, the notepad is simply incremented by the sum of the 1 face (9) repeatedly until it has the right value for each character, then prints it.

Comments are not for extended discussion; this conversation has been moved to chat.

@MartinEnder Could you move them to the existing chatroom instead?

@MDXF I could but I can't tell whether they'd end up being completely out of place and context in that chatroom.

@MartinEnder The comments are older than the chatroom, so they would just appear way back in the transcript, correct?

They would. Thanks, I'll move the messages.

Note that due to language updates, you can get a better score via calling @ implicitly - @6 can be shortened to @ in all cases.

C++, score: 4.026 3.998
improvement: added M, E and S rotations; now eats even more RAM
Fortunately, there is no memory limit here! This program can use over 10 GB of RAM, if you are unlucky enough.
Uses a heavily modified A*-like algorithm that doesn't find even nearly optimal solutions.
It takes at least 2 bytes to cause any change to the notepad, and another byte to print it, so getting a score below 3 is almost certainly impossible.
Uses a shamelessly stolen large part of the https://codegolf.stackexchange.com/a/104881 answer to "Simulate a Rubik's cube" (by user "cmaster - reinstate monica") (for some reason I remember golfing that answer, but I can't find any related comments).
//#define _GLIBCXX_DEBUG
#include <x86intrin.h>
#include <cstring>
#include <iostream>
#include <streambuf>
#include <bitset>
#include <cstdio>
#include <atomic>
#include <vector>
#include <algorithm>
#include <cmath>
#include <climits>
#include <random>
#include <set>
#include <list>
#include <map>
#include <unordered_map>
#include <deque>
#include <stack>
#include <queue>
#include <string>
#include <iomanip>
#include <unordered_set>
#include <thread>

#define faceMove(offset) {offset,offset+1,offset+2,offset+15,offset+28,offset+27,offset+26,offset+13}
int faceMoves[9][8] = {
    faceMove(3),    //Up
    faceMove(39),   //Left
    faceMove(42),   //Front
    faceMove(45),   //Right
    faceMove(48),   //Back
    faceMove(81),    //Down
    {0,0,0,0, 0,0,0,0}, //M
    {0,0,0,0, 0,0,0,0}, //E
    {0,0,0,0, 0,0,0,0}, //S (these 3 move the centers in Cubically)
}, lineMoves[9][12] = {
    {50,49,48,47,46,45,44,43,42,41,40,39},    //Up
    {3,16,29,42,55,68,81,94,107,76,63,50},    //Left
    {29,30,31,45,58,71,83,82,81,67,54,41},    //Front
    {109,96,83,70,57,44,31,18,5,48,61,74},    //Right
    {39,52,65,107,108,109,73,60,47,5,4,3},    //Back
    {65,66,67,68,69,70,71,72,73,74,75,76}, //Down
    {0*13 + 4, 1*13 + 4, 2*13 + 4, 3*13 + 4, 4*13 + 4, 5*13 + 4, 6*13 + 4, 7*13 + 4, 8*13 + 4, 5*13 + 10, 4*13 + 10, 3*13 + 10}, //M
    {4*13 + 0, 4*13 + 1, 4*13 + 2, 4*13 + 3, 4*13 + 4, 4*13 + 5, 4*13 + 6, 4*13 + 7, 4*13 + 8, 4*13 + 9, 4*13 + 10, 4*13 + 11}, //E
    {1*13 + 3, 1*13 + 4, 1*13 + 5, 3*13 + 7, 4*13 + 7, 5*13 + 7, 7*13 + 5, 7*13 + 4, 7*13 + 3, 5*13 + 1, 4*13 + 1, 3*13 + 1} //S
};
#undef faceMove
void cubeRotate(std::string& cube, int* move, int rotation)
{
    int sign = rotation < 0 ? -1 : 1;
    for(int* submove = move; submove != move + rotation; submove += sign)
    {
        char takeout = cube[submove[3*rotation]];
        for(int j = 3; j --> 0;) cube[submove[j * rotation + rotation]] = cube[submove[j*rotation]];
        cube[*submove] = takeout;
    }
}
std::string cubeMove(std::string cube, int move, int inverted)
{
    cubeRotate(cube, faceMoves[move + inverted] - inverted, inverted ? -2 : 2);
    cubeRotate(cube, lineMoves[move + inverted] - inverted, inverted ? -3 : 3);
    return cube;
}
std::string cubeStart = 1+R"(
   000
   000
   000
111222333444
111222333444
111222333444
   555
   555
   555      )";
std::array<char, 6> faceVals(const std::string& s)
{
    std::array<char, 6> fvs {};
    int xs[6] { 3, 0, 3, 6, 9, 3};
    int ys[6] { 0, 3, 3, 3, 3, 6};
    for(int i = 0; i < 6; i++)
    {
        char ts = 0;
        for(int y = ys[i]; y < ys[i] + 3; y++)
        for(int x = xs[i]; x < xs[i] + 3; x++)
            ts += s[y * 13 + x] - '0';
        fvs[i] = ts;
    }
    return fvs;
}
std::string target;
struct sstate
{
    int i;
    std::string cube;
    int notepad;
    char prevCmd;
    int movesSincePrint = 0;
    bool operator < (const sstate& rhs) const
    {
        return std::tie(i, notepad, cube, prevCmd) < std::tie(rhs.i, rhs.notepad, rhs.cube, rhs.prevCmd);
    }
    int heur() const
    {
        return 3 * (target.size() - i);
    }
};
std::vector<std::pair<sstate, char>> neighbours(sstate of)
{
    std::array<char, 6> fvs = faceVals(of.cube);
    std::vector<std::pair<sstate, char>> ans;
    if(target[of.i] == of.notepad) return {{{of.i+1, of.cube, of.notepad, '@', 0}, '@'}};
    for(char c : "+-*/X&|:_")
        ans.push_back({{of.i, of.cube, of.notepad, c}, c});
    if(of.prevCmd == '+' && of.notepad < 512)
        for(int i = 0; i < 6; i++)
        {
            if(of.notepad + fvs[i] > 512) continue;
            auto next = of; next.notepad += fvs[i]; ans.push_back({next, i+'0'});
        }
    if(of.prevCmd == '-' && of.notepad < 512)
        for(int i = 0; i < 6; i++)
        {
            if(of.notepad - fvs[i] > 512) continue;
            auto next = of; next.notepad -= fvs[i]; ans.push_back({next, i+'0'});
        }
    if(of.prevCmd == '*' && of.notepad < 512)
        for(int i = 0; i < 6; i++)
        {
            if(fvs[i] * of.notepad > 65536) continue;
            auto next = of; next.notepad *= fvs[i]; ans.push_back({next, i+'0'});
        }
    if(of.prevCmd == '/')
        for(int i = 0; i < 6; i++)
        {
            if(fvs[i] == 0) continue;
            auto next = of; next.notepad /= fvs[i]; ans.push_back({next, i+'0'});
        }
    if(of.prevCmd == 'X' && of.notepad < 512)
        for(int i = 0; i < 6; i++)
        {
            if((of.notepad ^ fvs[i]) > 512) continue;
            auto next = of; next.notepad ^= fvs[i]; ans.push_back({next, i+'0'});
        }
    if(of.prevCmd == '&')
        for(int i = 0; i < 6; i++)
        {
            auto next = of; next.notepad &= fvs[i]; ans.push_back({next, i+'0'});
        }
    if(of.prevCmd == '|' && of.notepad < 512)
        for(int i = 0; i < 6; i++)
        {
            if((of.notepad | fvs[i]) > 512) continue;
            if(fvs[i] == 0) continue;
            auto next = of; next.notepad |= fvs[i]; ans.push_back({next, i+'0'});
        }
    if(of.prevCmd == '_')
        for(int i = 0; i < 6; i++)
        {
            if(fvs[i] == 0) continue;
            auto next = of; next.notepad %= fvs[i]; ans.push_back({next, i+'0'});
        }
    if(of.prevCmd == ':')
        for(int i = 0; i < 6; i++)
        {
            auto next = of; next.notepad = fvs[i]; ans.push_back({next, i+'0'});
        }
    if(of.cube != cubeStart) { auto next = of; next.prevCmd = '~'; next.cube = cubeStart; ans.push_back({next, '#'}); }
    std::string moves = "ULFRBDMES";
    for(int i = 0; i < 9; i++)
    if(of.prevCmd == moves[i])
    {
        auto next = of;
        next.cube = cubeMove(next.cube, i, false);
        next.cube = cubeMove(next.cube, i, false);
        next.prevCmd = '~';
        ans.push_back({next, '\''});
    }
    if(of.movesSincePrint < 1 || (of.movesSincePrint == 1 && 'A' <= of.prevCmd && of.prevCmd <= 'Z'))
    for(int i = 0; i < 9; i++)
    {
        auto next = of;
        next.cube = cubeMove(next.cube, i, false);
        next.prevCmd = moves[i];
        next.movesSincePrint++;
        ans.push_back({next, moves[i]});
    }
    return ans;
}
struct astate
{
    sstate ss;
    int f;
    bool operator < (const astate& rhs) const
    {
        if(f != rhs.f) return f < rhs.f;
        if(ss.heur() != rhs.ss.heur()) return ss.heur() < rhs.ss.heur();
        return ss < rhs.ss;
    }
};
std::string metagolf(std::string target)
{
    ::target = target;
    std::map<sstate, std::pair<sstate, std::string>> prev;
    astate start = {{0, cubeStart, 0, '~'}, 0};
    std::map<sstate, int> dists; dists[start.ss] = 0;
    std::set<astate> openset; openset.insert(start);
    int nodes = 0;
    std::vector<int> ics(target.size() + 3);
    sstate best; int bestdist = INT_MAX; bool done = false;
    std::vector<std::set<std::string>> cubes(target.size() + 1);
    int itsleft = 10000;
    int curI = 0;
    int lastChange = 0;
    while(!openset.empty() && (!done || itsleft --> 0))
    {
        auto it = openset.begin();
        auto[cs, cf] = *it; openset.erase(it);
        int cd = dists[cs];
        if(cs.i == target.size()) { if(cd < bestdist) bestdist = cd, best = cs; done = true; continue; }
        if(cs.i < curI) continue;
        if(cs.i > curI) cubes[cs.i].insert(cs.cube);
        if((cubes[cs.i].size() > 1000 && cs.i > curI) || (cubes[cs.i].size() > 0 && cs.i > curI && nodes - lastChange > 5e4)) curI = cs.i, lastChange = nodes;
        if(nodes % 128 == 0) printf("n=%d, cf=%d, i=%d, notepad=%d, tc=%d\r", nodes, cf, cs.i, cs.notepad, target[cs.i]);
        nodes++;
        for(auto[next, cmd] : neighbours(cs))
        {
            if(dists.count(next) && dists[next] <= cd + 1) continue;
            dists[next] = cd + 1;
            prev[next] = {cs, std::string(1, cmd)};
            openset.insert((astate){next, cd + 1 + next.heur()});
        }
    }
    std::string ans = "";
    while(prev.count(best))
    {
        auto[pr, cmd] = prev[best];
        best = pr;
        ans += cmd;
    }
    std::reverse(ans.begin(), ans.end());
    return ans;
}
std::string gen_random(int len)
{
    static const char alphanum[] = "0123456789"
            "~!@#$%^&*()_+`-=[]\\;',./{}|:\"<>?" //this is obviously not alphanumeric
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            "abcdefghijklmnopqrstuvwxyz";
    std::string s;
    while(len --> 0) s += alphanum[rand() % (sizeof(alphanum) - 1)];
    return s;
}
int main()
{
    //auto cube = cubeStart;
    //for(int i = 0; i < 9; i++) cube = cubeMove(cube, i, 0);
    //for(int i = 0; i < 9; i++) cube = cubeMove(cube, i, 1);
    //printf("%s\n", cube.data());
    double ans = 0;
    for(int i = 0; i < 100; i++)
    {
        std::string s = gen_random(rand() % 35 + 5);
        std::string code = metagolf(s);
        printf("%s: %s\n", s.data(), code.data());
        ans += code.size() * 1.0 / s.size();
    }
    printf("%lf\n", ans * 1.0 / 100);
    //std::string ts = "Hello, World!";
    //int n = ts.size();
    //printf("%s\n", metagolf(ts).data());
}

To avoid Unicode handling, this program performs certain character substitutions: X corresponds to ⊕, & to ·, and # to ▦.
I used this to create an answer to "Hello, World!": https://codegolf.stackexchange.com/a/206322

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


text:
Create a percent sign
Given an integer n ≥ 1, output a 2D representation† of a percent sign of width n. The construction goes as follows:

Create an n by n matrix (or list of lists) filled with zeroes.
Insert ones in the top-left and bottom-right corners.
Place ones on the diagonal from the bottom-left to the top-right.

For input n = 4, this construction would look like:
1. 4x4 matrix of 0s
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
2. 1s in TL and BR corners
1 0 0 0
0 0 0 0
0 0 0 0
0 0 0 1
3. 1s across BL-TR diagonal
1 0 0 1
0 0 1 0
0 1 0 0
1 0 0 1

This is a code-golf, so the shortest program in bytes wins.
† I use a matrix of 1s and 0s, but it is also acceptable to use a string of any non-whitespace character and spaces. So, the example above could look like:
#  #
  #
 #
#  #

or
#     #
    #
  #
#     #

Test cases
n
output

1
1

2
1 1
1 1

3
1 0 1
0 1 0
1 0 1

4
1 0 0 1
0 0 1 0
0 1 0 0
1 0 0 1

10
1 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 1

Final note
Adding an explanation would be greatly appreciated.

Can our solutions be 0-indexed?

@Cowsquack I'd say no. You're receiving the width, not an index.

Can we output a list of lists?

@xnor Yes; list of lists and matrix are synonymous in my post. I'll add that to the question

Note that this is '1'+'0'*(n-2) with whitespace inserted

Jelly, 6 bytes
²Rm’Ṭs

Try it online!
How it works
²Rm’Ṭs  Main link. Argument: n

²       Square; yield n².
 R      Range; yield [1, ..., n²].
   ’    Decrement; yield n-1.
  m     Modular; yield every (n-1)-th element of the range, staring with the first.
    Ṭ   Untruth; yield a Boolean array with 1's at the specified indices.
     s  Split the resulting array into chunks of length n, creating a matrix.

Also, ²Ḷ%’¬s or +þ%’=2

²Ḷọ’s is so close...

If only there were a 1-byte "x is divisible by y" link...

@ETHproductions There's ḍ@ but that's two bytes.

And I thought I was clever with ⁼þµ+1¦Ṫṁ³UG...until a Dennis ²-something solution popped up.

JavaScript (ES6), 52 bytes
n=>[...Array(n)].map((_,y,a)=>a.map(_=>y++%~-n<1|0))

V, 15 bytes
Àé ÀÄ|r#L.|ò.kl

Try it online!
Explanation
Àé<space>        " Argument times insert a space
ÀÄ               " Argument times duplicate this line
                 " This gives an arg-by-arg matrix of spaces
                 "  and brings the cursor to the end of the first line
|r#              " Go to the beginning of this line and replace the first character with #
L.               " Go to the end of this matrix (bottom-right corner) and replace that character with a #
|                " Go to the beginning of the last line
ò                " Recursively do:
 .               "  Repeat the last action, r#, replace the character under the cursor with #
 kl              "  Go 1 up and 1 right

Python 2, 58 57 bytes
n=input()
x='#'.ljust(n-1)*3
exec'print x[:n];x=x[1:];'*n

Try it online!

Dyalog APL, 12 11 10 bytes
,⍨⍴×,2↓⊢↑×

Try it online
-1 byte thanks to lstefano.
How?
,⍨⍴×,2↓⊢↑×
       ⊢↑× - argument-length extension of the sign of the argument (1)
     2↓    - Drop the first two elements
   ×,      - Prepend a one
,⍨⍴        - Shape into a square array with dimensions of input x input

I seriously don't think this can be golfed anymore... wow.

It can: ,⍨⍴×,2↓⊢↑× (10 bytes). I am tempted to add: don't use too many commutes... :-P

Try online with arg 5 - Try online with arg 1

You've got to be kidding me, wow. Nice abuse of signum.

MATL, 7 bytes
XyPl5L(

Try it at MATL Online!
Explanation
Create identity matrix (Xy), flip vertically (P), write (() value 1 (l) to the first and last entries (5L), which are the top left and bottom right.

GNU APL, 17 15 bytes
{1=⍵∨⍵⍵⍴1=⍳⍵-1}

This is one weird day ... GNU actually beat Dyalog APL ... woah.
TIO doesn't support GNU APL ...
Explanation (input is ⍵):
1=⍳⍵-1 - 1 followed by ⍵-2 0's
⍵⍵⍴    - fit into a square
⍵∨     - gcd ⍵ (0 gcd n = n)
1=     - test each element for equality with 1

Ninja'd?

There ... take that.

Can't believe I actually had to break out my old GNU APL, wow.

And take that!!

Ooh, I am going to take inspiration from the 1=⍵∨ and implement it in my solution

I'm assuming then it will basically be my answer but with a space then?

Eh, you're probably right

But I've beaten myself again ... this time in Dyalog APL again (I can't believe how substantially different all these answers are ... wow)

Python 2, 46 bytes
lambda n:zip(*[iter(`10L**n`[:-3]*-~n+'1')]*n)

Try it online!
Outputs like
[('1', '0', '0', '1'), ('0', '0', '1', '0'), ('0', '1', '0', '0'), ('1', '0', '0', '1')]

Python 2, 48 bytes
lambda n:zip(*[iter([1]+(n*[0]+[1])[2:]*-~n)]*n)

Try it online!
Outputs like
[(1, 0, 0, 1), (0, 0, 1, 0), (0, 1, 0, 0), (1, 0, 0, 1)]

Python 3, 48 bytes
lambda n:('%d'*n+'\n')*n%(1,*(*[0]*n,1)[2:]*-~n)

Try it online!
A quite different string-substitution approach in Python 3. Outputs like:
1001
0010
0100
1001

Can't you make 10L 10?

@Zacharý I'm relying on there always being an L at the end so I can cut the same number of characters off the end of large numbers and small ones.

Oh, sorry, I mistakenly thought you were only using it as the number. I never knew 10 and 10L were different.

Jelly, 9 bytes
=þ¹UF1Q¦s

Try it online!
How it works
=þ¹UF1Q¦s  Main link. Argument: n

  ¹        Identity; yield n.
=þ         Equals table; compare each i in [1, ..., n] with each j in [1, ..., n].
           This yields the n×n identity matrix.
   U       Upend; reverse each row.
    F      Flatten the matrix.
       ¦   Sparse application:
      Q        Unique; yield the unique elements of the constructed array, i.e.,
               [1] if n = 1 and [0, 1] if n > 1.
     1         Yield 1.
           This replaces the elements at indices 0 (last) and 1 (first) with 1.
        s  Split the resulting array into chunks of length n.

APL (Dyalog), 18 bytes
{⍵=1:⍵⋄⍵ ⍵⍴1=⍳⍵-1}

Try it online!
Making this work for input 1 has added 6 bytes.
Looking at testcase 4, we see the output is
1 0 0 1
0 0 1 0
0 1 0 0
1 0 0 1

This is basically 1 0 0 repeated throughout the matrix. In other words, 1 0 0 shaped in a 4-by-4 matrix. So in this solution, we first generate this vector with 1 and trailing 0s using 1=⍳⍵-1 and then shape it using ⍵ ⍵⍴. But this borks for input 1, so we need to create a conditional and gain 6 bytes...
{⍵=1:⍵⋄⍵ ⍵⍴1=⍳⍵-1}    The right argument is ⍵
 ⍵=1:⍵                 If ⍵ is 1 return itself
⋄                      Otherwise
 ⍳⍵-1                   Create a range 1 .. ⍵-1
 1=                     Equals 1; 1 0 0 {⍵-2 0's} ...
 ⍵ ⍵⍴                   Shape in a ⍵-by-⍵ matrix

Could you replace the conditional with 1⌈⍵-1? i.e. {⍵ ⍵⍴1=⍳1⌈⍵-1}

R, 54 42 bytes
-12 bytes thanks to Jarko Dubbeldam
n=scan();m=diag(n)[,n:1];m[1,1]=m[n,n]=1;m

returns a matrix; reads from stdin. creates an identity matrix diag(n), flips it top to bottom [,n:1], sets the top left and bottom right to 1, and then writes to console ('') with width n.
Try it online!

You are allowed to output a matrix, so you can save a few bytes by turning it into a function (pryr::f).

@JarkoDubbeldam I could, but then I think I'd have to change the language to R+pryr so I'd consider that a separate language; you're free to submit that! Then you could use the idea from Cows quack's answer which I think would be even shorter than this in that context (a 1-liner).

Hmm, I am unsure where to draw the line to be honest. Would you consider any library used a different language?

Also, using function(n) would probably still be shorter

@JarkoDubbeldam I'm really toying with the idea of simply eschewing anything that's not base R; so using basically anything that's not in the base installation is a "different language" in my mind

Which is shorter than the oneliner implementation you referenced: function(n)matrix(rep(c(1,rep(0,n-2)),n+1),n,n)

@JarkoDubbeldam nah, scan is still better since there's only one input (if I'm not gonna be using pryr)

Nevermind: pryr::f(matrix(c(1,rep(0,n-1)),n,n)).

@JarkoDubbeldam oh, nice one. I'd even submit that as its own answer; it's different enough in the way it's constructing the matrix!

Let us continue this discussion in chat.

05AB1E, 14 11 7 bytes
n<ÝI<Öô

Try it online!
Explanation
n<Ý      # push range [0 ... n^2-1]
   I<Ö   # check each for equality to 0 when modulus with n-1 is taken
      ô  # split in pieces of size n

Haskell, 55 bytes
At first my approach was to recursively generate the transposed identity matrix, but then fixing the first and last line required some ugly/lengthy case distinctions. So I looked for another way to generate the identity matrix which is how I found this idea.
f n=[[sum[1|x+y`elem`[2,n+1,2*n]]|y<-[1..n]]|x<-[1..n]]

Try it online!
Explanation
[[x+y|y<-[1..n]]|x<-[1..n]]

generates this matrix (for n=4):
[2,3,4,5]
[3,4,5,6]
[4,5,6,7]
[5,6,7,8]

As you can see the top left element is 2 (in general), all the diagonal elements are 5 (in general n+1) and the bottom right element is 8 (in general 2*n). So all we need to do is to check if x+y is an element of [2,n+1,2*n].

Easyfuck, 21 19 bytes

EM:␗Èc°NSHYå·Ñß'xSHYâÛNBSP

due to lack of unicode representations for c1 control characters, they have been replaced by their superscripted abbreviations
Decompressed:
"S'!>!G0'+<[>G>'<+<-]

"S'                   take input, put it into storage and output 0
   !>!G0'             move cursor to [input, input] and output 0
         +<[>G>'<+<-] move cursor to [input, 1] and output 0s while moving to [1, input]

C# (.NET Core),121 91 88 bytes
-30 bytes because the old way was stupid.
-3  bytes by moving around the variable initialization

n=>{int i=0,k=n-1;int[,]b=new int[n,n];b[0,0]=b[k,k]=1;for(;i<n;)b[i++,k--]=1;return b;}

Try it online!
Loops iterates down the array to fill in the 1's. Returns an array of 1's and 0's.

Declare b as var to save some bytes.

Charcoal, 14 12 7 bytes
-5 bytes thanks to Neil!
↗Ｎ⸿/‖Ｏ↘

Try it online!

I don't think this can be any shorter...

Well, first I trimmed it to Ｎν◨/ν←↙ν‖Ｏ↘, but then I came up with ↗Ｎ⸿/‖Ｏ↘!

@Neil Wow, I don't even know what ⸿ does. Does it reset to original position?

No, ⸿ is like ¶ in that it moves down a row but it always goes to column zero (as measured by Ｊ) rather than the column at the beginning of the string, so for example Ｊ⁵¦⁵⸿ is the same as Ｊ⁰¦⁶.

PowerShell, 67 bytes
param($n)0..--$n|%{-join(("1"+"0"*(($n-1),0)[!$n])*3)[$_..($_+$n)]}

Try it online!
Takes input $n and loops from 0 to --$n (i.e., $n pre-decremented). Each iteration, we construct a string of 1 followed by $n-1 0s, then multiply that out 3 times (e.g., 100010001000 for input of 5). Then we index into that on a rotating basis starting from 0 to 0 + $n. Those characters are -joined into a string, which is left on the pipeline. Output is implicit.

(NB -- This requires an additional 9 bytes to handle the special case of n=1. Below is the 58-byte code if we're guaranteed n>1)
param($n)0..--$n|%{-join(("1"+"0"*($n-1))*3)[$_..($_+$n)]}

C++, 144 bytes
#include<string>
#define S std::string
S p(int n){S r;for(int i=0;i<n;++i){r+=S(n,32);r[r.size()-1-i]=35;r+=10;}r[0]=r[r.size()-2]=35;return r;}

It takes advantage of the one byte difference between '#' and 35

Where exactly does your code take advantage of the one byte difference between '#' and 35?

@Zacharý It seems it was in my IDE x)

Python 2, 86 62 bytes
n=input();a=('1'+'0'*(n-2))*2+'1'
exec'print a[:n];a=a[1:];'*n

Try it online!
-24 bytes: Thanks to an idea from Rod!

Mathematica, 72 bytes
(s=Table[0,#,#];s[[1,1]]=s[[#,#]]=1;Table[s[[#+1-i,i]]=1,{i,#}];Grid@s)&

input

[5]

output

1  0   0   0   1
0   0   0   1   0
0   0   1   0   0
0   1   0   0   0
1   0   0   0   1

The problem doesn't ask you to print/display it, so you can replace Grid@s with s to save 5 bytes.

Dyalog APL v16, 23 bytes
{(1@(1 1)(⍵ ⍵))⌽∘.=⍨⍳⍵}

Try it online!
Explanation:
{(1@(1 1)(⍵ ⍵))⌽∘.=⍨⍳⍵} -(input ⍵)
                ∘.=⍨⍳⍵  - identity matrix with size ⍵×⍵
               ⌽        - flip that
 (1@(1 1)(⍵ ⍵))         - place 1 into the corners using the v16 operator @ (At)

Japt, 12 bytes
²ovUÉ hT1 òU

Returns a 2D array / matrix.
Try it online! using the -Q flag to show array-formatted output.
Explanation
²ovUÉ hT1 òU

Implicit: U = input integer
²o

Square U (²), create the array [0, U*U) (o), and map each item by...
vUÉ

1 if it's divisible (v) by U-1 (UÉ), else 0.
hT1

Set the item (h) at index 0 (T) to 1.
òU

Split the array into slices (ò) of length U.

I don't think you actually need the hT1, as 0 is technically already divisible by U for every U. Other than that, great job :-)

@ETHproductions That was added to deal with an input of 1. Without it, it returns [[0]] because apparently zero is not divisible by zero.

Ah, dang it. I don't know if I should fix that though...

Lua, 117 bytes
m=arg[1]+0 for y=m,1,-1 do s=""for x=1,m do s=s..((x==1 and y==m or x==m and y==1 or x==y)and"#"or" ")end print(s)end
Try it
Code is pretty simple. It sets m to the first argument, then adds 0 to it to convert it to a number, then iterates backwards for the Y coord, forward through the X coord and will put a # if x==y or if it's the other corners.
This program never uses the keyword "if".

Octave, 37 bytes
@(n)sparse([1 n:-1:1 n],[1 1:n n],!0)

Try it online!
Generates a sparse matrix representing the percent sign.

PHP, 53 bytes
for(;$i<$l*$l;)echo($i++%($l-1)?0:1).($i%$l?'':"\n");

The length of the side of the matrix is $l. This code has a PHP Notice and even a PHP Warning for division by 0 when $l=0, but does the job!

It seems that you expect the input to be stored in a predefined variable (->$l). Unfortunately this is not one of our accepted ways to take input. In the linked meta post you'll find alternatives, e.g. using command line arguments as seen in ricdesi's  answer.

completed and golfed: while($i**.5<$n=$argn)echo$i++%~-$n?0:1,"\n"[$i%$n]; or while($i**.5<$n=$argn)echo+!($i++%~-$n),"\n"[$i%$n]; (52 bytes each)

Needs <? at the beginning.

Python 2, 93 bytes
n=input()
a='1'+'0'*(n-2)+'1'
print a
for i in range(1,n-1):print str(10**i).zfill(n)
print a

Try it online!

Good try, but doesnt work for n=1.

Python 3, 97 bytes
def f(n):
    m=[[0+(j==n-i-1)for j in range(n)]for i in range(n)]
    m[0][0]=1
    m[-1]=m[0]
    return m

Explanation
m=[[0+(j==n-i-1)for j in range(n)]for i in range(n)]
This is a list comprehension, the 0+(j==n-i-1) is a shorter way to convert j==n-i-1 to an int (as opposed to int function)
and then m[-1]=m[0] is shorter than making bottom right 1, as top and bottom rows are identical.

Mathematica, 59 56 48 bytes
(x=Sort@IdentityMatrix@#;x[[1,1]]=x[[#,#]]=1;x)&

The identity matrix has a diagonal of 1s, but it's going the wrong way. Sorting the rows fixes this. Then we set the corners to be 1 as well, and return the matrix.
You can test this out in the Wolfram Cloud sandbox by pasting code like the following and clicking "Evaluate cell" or hitting Shift+Enter or the numpad Enter:
(x=Sort@IdentityMatrix@#;x[[1,1]]=x[[#,#]]=1;x)&@5//ArrayPlot

Longer solutions
SparseArray[#->1&/@{Band[{1,#},{#,1},{1,-1}],{1,1},{#,#}}]&

The #->1& is an anonymous function that associates the input with 1, and the Band represents the coordinates from {1,#} to {#,1} going in steps of {1,-1}.
f[n_]:=Boole[#==#2==1||#==#2==n||#+#2==n+1]&~Array~{n,n}

This builds an n by n array where the values are 1 or 0 depending on the truth of "both indices are 1 or both indices are n or both indices sum to n+1".

Forth, 273 ( without comments ) 170 ( golfed-ish )
: % 2 base ! cr dup 1- 1 swap lshift 1 or . cr 2 over 2 - dup 0< 0= if
0 ?do 2dup s>d rot <# 0 ?do # loop #> type cr 2*  loop
1 or . else drop drop then cr drop decimal ;

( 273 version to clarify commented version: )
: newbase
 base @ swap base ! ;
: 0u.r
 swap s>d rot <# 0 ?do # loop #> type ;
: frame
 1- 1 swap lshift 1 or ;
: %
 2 newbase swap
 cr dup frame . cr
 2 over 2 -
 dup 0< 0= if
  0 ?do
   2dup swap 0u.r cr
   2*
  loop
  1 or .
 else
  drop drop
 then
cr
drop base ! ;

( Note that, since whitespace is the primary delimiter in Forth, removing every carriage return would make no difference. Indentation, of course, does. )
( Commented: )
( Uses bit array, max 64 width on AMD64 with gforth. )

( Could shave an extra thirty or so bytes by not restoring )
( the numeric base, )
( and a few more by pulling frame and 0u.r into the definition. )

: newbase ( n -- oldbase )  ( swap base with n )
 base @ swap base ! ;

: 0u.r ( u width -- )  ( unsigned numeric output, no leading zero suppression )
 swap s>d rot <# 0 ?do # loop #> type ;

: frame ( n -- f )  ( frame )
 1- 1 swap lshift 1 or ;

: %  ( n -- )  ( Make the % sign )
 2 newbase swap ( Use binary output. )
 cr dup frame . cr ( Frame the first line. )
 2 over 2 -
 dup 0< 0= if ( Are we already done? )
  0 ?do ( Loop doesn't do the first or last. )
   2dup swap 0u.r cr ( Zero fill, right justify. )
   2*
  loop
  1 or . ( Put the second frame out. )
 else
  drop drop
 then
cr
drop base ! ;

( Execution examples: )
1 %
1

 ok
2 %
11
11
 ok
3 %
101
010
101
 ok
10 %
1000000001
0000000010
0000000100
0000001000
0000010000
0000100000
0001000000
0010000000
0100000000
1000000001
 ok
40 %
1000000000000000000000000000000000000001
0000000000000000000000000000000000000010
0000000000000000000000000000000000000100
0000000000000000000000000000000000001000
0000000000000000000000000000000000010000
0000000000000000000000000000000000100000
0000000000000000000000000000000001000000
0000000000000000000000000000000010000000
0000000000000000000000000000000100000000
0000000000000000000000000000001000000000
0000000000000000000000000000010000000000
0000000000000000000000000000100000000000
0000000000000000000000000001000000000000
0000000000000000000000000010000000000000
0000000000000000000000000100000000000000
0000000000000000000000001000000000000000
0000000000000000000000010000000000000000
0000000000000000000000100000000000000000
0000000000000000000001000000000000000000
0000000000000000000010000000000000000000
0000000000000000000100000000000000000000
0000000000000000001000000000000000000000
0000000000000000010000000000000000000000
0000000000000000100000000000000000000000
0000000000000001000000000000000000000000
0000000000000010000000000000000000000000
0000000000000100000000000000000000000000
0000000000001000000000000000000000000000
0000000000010000000000000000000000000000
0000000000100000000000000000000000000000
0000000001000000000000000000000000000000
0000000010000000000000000000000000000000
0000000100000000000000000000000000000000
0000001000000000000000000000000000000000
0000010000000000000000000000000000000000
0000100000000000000000000000000000000000
0001000000000000000000000000000000000000
0010000000000000000000000000000000000000
0100000000000000000000000000000000000000
1000000000000000000000000000000000000001
 ok

( Final note: works to one less than the bit width of the Forth interpreter. I ran the above on gforth, AMD64. An ancient 16-bit Forth would only go to 15 bits wide, and would need a bit of modification. )

If you want to have the commented code in your answer that's fine, but you do need the golfed down code somewhere, too.

@Phoenix Thanks. Done.

J, 14 bytes
-]\*:$1,0$~-&2

Ungolfed:
- ]\ (*: $ (1,0 $~ -&2))

Try it online!

Food for thought: a 10 byte solution exists :)

@ConorO'Brien Damn you.  It's already past 3 am here :P

Same here, and here we are :D

@ConorO'Brien Was it 0=<:|i.@,~?

@miles yes, it was :)

Ruby, 47 bytes
->n{([1]+[0]*(n-2)).cycle.each_slice(n).take n}

It returns an array of arrays.
The code is pretty straightforward.

It creates a n-1 array with 1 as the first element and the rest filled with 0s (e.g. [1, 0, 0, 0])
It repeats it
It takes n slices of n elements

Try it online!

C, 216 212 186 155 145 Bytes
Just as a function that takes a matrix as input
f(int i,int **m){for(int a=0;a<i;a++){for(int b=0;b<i;b++){m[a][b]=((a+b+1==i)||(!a&&!b)||(a==i-1&&b==i-1))?1:0;printf("%d ",m[a][b]);}puts();}}

6 Bytes thanks to Conor O'Brien!
4 Bytes thanks to Zacharý!
Old Answer
main(int i){int**m=malloc(8*i);for(int a=0;a<i;a++){m[a]=malloc(4*i);for(int b=0;b<i;b++){m[a][b]=((a+b+1==i)||(a==0&&b==0)||(a==i-1&&b==i-1))?1:0;printf("%d ",m[a][b]);}printf("\n");}}

Instead of taking an array of arguments in the main function, it uses the length of arguments instead so the input for a 4x4 matrix would be:

Old Answer
main(int c,char **v){int i=atoi(v[1]);int**m=malloc(8*i);for(int a=0;a<i;a++){m[a]=malloc(4*i);for(int b=0;b<i;b++){m[a][b]=((a+b+1==i)||(a==0&&b==0)||(a==i-1&&b==i-1))?1:0;printf("%d ",m[a][b]);}printf("\n");}}

If only I could get rid of of those mallocs, I know C is not a great golfing language, but whatever!
Compiled with GCC on macOS Sierra.
Ungolfed
main(int i) {
int **m = malloc(8 * i);    // Create n*n matrix
for(int a=0; a<i; a++) {    // Iterate through rows
    m[a] = malloc(4 * i);   // Allocate rows
    for(int b=0; b<i; b++) {    // Iteratre columns
        // Add a 1 to cell if its start or finish, or diagnol
        m[a][b]=((a+b+1==i)||(a==0&&b==0)||(a==i-1&&b==i-1))?1:0;
        printf("%d ",m[a][b]); // Print cell
    }
    printf("\n");           // Print row
}

Usage

Awesome thanks I just got start golfing, thanks for the help!

If you change your IO method to accepting a parameter as input, then outputting to STDOUT, then I think f(i){int a,b;for(a=0;a<i;a++){for(b=0;b<i;b++)printf("%d ",a+b+1==i||!a&&!b||a==i-1&&b==i-1);printf("\n");}} works.

Instead of printf("\n") you can do puts("")

Okay, is it okay if I post my solution separately due to the differing IO method?

Ya sure it's all casual for me

Google Sheets, 58 bytes
=If(A1=1,1,RegexReplace(Rept(10^(A1-2),A1+1)&1,"(.{"&A1&"})","$1
"))

Input is in A1.
Explanation:

10^(A1-2) generates a one followed by n-1 zeroes.
Rept(10^(A1-2),A1+1)&1 generates n+1 copies of that sequence with
an extra one at the end. For n=5 as an example, that string is
1000100010001000100010001.
RegexReplace(~,"(.{"&A1&"})","$1\n")
replaces every grouping of n characters with itself plus a line
break. (In the actual formula, I use a literal line break rather than
the escaped \n.)
This breaks on n=1 because 10^-1 = 0.1 so the string is 0.10.11. The If at the beginning escapes that special case.

Results:

I took the screenshot of exactly those cells and the image turned out to be 323 x 232 pixels. I think that's neato.

C# (.NET Core), 65 bytes
w=>{var l=new int[w*w];for(int i=0;i<w*w;i+=w-1)l[i]=1;return l;}

Try it online!
The algorithm is significantly distinct from the other C# answer, so I decided to post it separately rather than as an improvement. Inspired by the top rated Jelly answer actually, I was doing something slightly less compact before. The output is a linear array, so would require some logic to wrap it into a 2D outside the method as-is. An alternate version requires 6 additional bytes to output as a true 2D array:
w=>{var l=new int[w,w];for(int i=0;i<w*w;i+=w-1)l[i/w,i%w]=1;return l;}

I also have an interesting non-competing version.
using System.Linq;w=>new int[w*w].Select((_,i)=>i%(w-1)<1)

This ends up with almost the right output, resulting in an IEnumerable<bool> with true/false instead of 1/0, and it's a linear rather than 2D structure, and although not needed for that exact line of code, using System.Collections.Generic is necessary to do anything useful with the output. Like I said, it's very close to being valid but not quite.

For the second using a ternary as in ?1:0 works and I believe an array of the result should be fine. The collections using also isn't necessary for that code.

For the first, would setting w*w to a variable and moving the int declaration out of the loop save you anything?

@TheLethalCoder Replacing the two instances of w*w with a single character variable saves 4 bytes, moving int i=0 outside the loop requires a semicolon which costs 1 byte, and then adding ,s=w*w to the declaration costs 6 bytes, so it actually nets +3 bytes.

You should use the byte count of the full 2D-representation solution. The array returned by the shorter solution would at least need to include some sort of delimiter to be valid.

Vyxal r, 6 bytes
‹?²ʁḊẇ

Try it Online!
‹      # n-1
 ?²ʁ   # 0...n^2
    Ḋ  # Foreach, is it divisible by (n-1)?
     ẇ # Split into chunks of (implicit input) length.

Uiua SBCS, 10 bytes
↯▽2:⊂1↘2⊚.

Try it!
Port of Adalynn's APL answer.
↯▽2:⊂1↘2⊚.
         .  # duplicate
        ⊚   # list of n zeros
      ↘2    # drop first two
    ⊂1      # prepend one
↯▽2:        # reshape to nxn

TIL scalar where, nice

Alternate 10: ↯:⊂1↘2⊃⊚⊟.

Retina, 44 bytes
\d+
$*
 $
#
+` ( *)#( *)$
$&¶$1#$2
^ | $
#

Try it online!

Python 3, 71 67 65 76 bytes
lambda n:n>1and''.join(' #'[i%~-n<1]+'\n'*(-~i%n<1)for i in range(n*n))or'#'

Try it online!

Retina, 24 bytes
.+
$*
.
$'#$`¶
^ | ¶$
#

Try it online! Explanation: The second line ends in a space, so the first stage converts the input into a row of spaces. The second stage then replaces each space in the row with a # in turn, collecting the resulting lines together. The final stage then adds the corner #s.

R (+pryr), 36 bytes
pryr::f(matrix(c(1,rep(0,n-1)),n,n))

Evaluates to the function:
function (n)
matrix(c(1, rep(0, n - 1)), n, n)

Which is a port from this APL answer.

PHP, 131 bytes
<?$m=$n=0;while($m<$argv[1]){while($n<$argv[1]){echo($m==$n&&(!$m||$m==$argv[1]-1)||$m+$n==$argv[1]-1)*1;$n++;}echo"\n";$m++;$n=0;}

Exploded view
<?  $m = $n = 0;
    while ($m < $argv[1]) {
        while ($n < $argv[1]) {
            echo ($m == $n && (!$m || $m == $argv[1]-1) ||
                  $m + $n == $argv[1]-1) * 1;
            $n++;
        }
        echo "\n";
        $m++;
        $n = 0;
    }

Not my best work, I'm certain I can golf this down.

Add $a=$argv[1]; at the beginning and replace all $argv[1] with $a to save several bytes.

Also take $n= out of the top 0 assignment and move $n=0; from the end of the outer loop to the beginning to save another 3 bytes.

Actually, 14 18 bytes
A simple algorithm.
Edit: Fixing a bug for n == 1
;;D╤$0D@H@u*'1@+╪i

Ungolfing
                    Implicit input: n
;;                  Duplicate n twice.
  D╤$               Push str(10**(n-1))
     0D@H           Push str(10**(n-1))[:-1]
         @u*        Push str * (n+1)
            '1@+    Append a "1"
                ╪   Split into chunks of length n
                 i  Flatten this list onto the stack
                    Implicit print

Try it online!

Gaia, 7 bytes
s…@(Ė¦/

Try it online!
Explanation
s        Square n
 …       Get the range from 0 to n^2-1
  @(     Push n-1
    Ė¦   For each number in the range, check if n-1 divides it
      /  Split into slices of size n

Perl 5, 67 57 + 1 (-p) = 58 bytes
$\=$_=10**$_/10+($_>1);for$i(2..y///c){say;s/.//;$_.=0}}{

Try it online!
Takes the input implicitly (-p). Convert that to 10 to the power of the input minus 1 and add one if the input is greater than one.  Outputs that as a string, then removes first character and appends a 0, looping until it has output n-1 rows.  For the last row, implicitly output the copy of the first row which has been stored in $\.

Java 8, 74 bytes
Essentially just a port of Kamil's second C# solution here.
n->{int g[][]=new int[n][n],i=0;for(;i<n*n;i+=n-1)g[i/n][i%n]=1;return g;}

Try It Online

WC, 92 bytes
;>_0|$-$-!!_1|;>@5|$''[<]!!$!_1|;>(?##@2|;>@5|$''[<<<]!!$!_1|?$-[>>>];</#)*$?!!_1|[>]!!$!_1|

Input
Artifact 0: a number ex. 5
Artifact 1: a string ex. #
Output
#   #
   #
  #
 #
#   #

Explanation
;>_0|                  Create variable set to artifact 0
$-$-                   Decrement twice
!!_1|                  Print artifact 1 with no newline
;>@5|                  Create variable set to global 5 (the space character)
$''[<]                 Repeat variable times the previous variable
!!$                    Print with no newline
!_1|                   Print artifact 1 with newline
;>(                    Create variable as function
   ?                   Reset variable index to 0
   ##@_2|              Start if-not statement, runs if not global 2 (zero)
      ;>@5|            Create variable set to global 5 (the space character)
      $''[<<<]         Repeat variable times index-3 (first variable)
      !!$              Print with no newline
      !_1|             Print artifact 1 with newline
      ?$-              Reset index to 0 and decrement
      [>>>]            Move index up 3
      ;<               Delete at index
      /                Restart context
   #                   End statement
)                      End function
*$?                    Call function and reset index
!!_1|                  Print artifact 1 with no newline
[>]!!$                 Move index up 1 and print with no newline
!_1|                   Print artifact 1 with newline

NOTE: Do NOT set artifact 1 to 1, it will freeze. Works for n > 1
Try it online!

Perl 5, 66 bytes
$n=pop;$_='#';for$x(0..$n){$_.=$"x($n-2).'#'};s/(.{$n})/$1\n/g;say

Takes input as first command line argument.
Builds up a string of length n^2 with # at the proper spots, then inserts newlines at the right places.

Husk, 9 bytes
´Ṫȯ¬%←¹+ŀ

Try it online! This function creates a matrix with indices from the range [0..n) and tests that their sum is divisible by n - 1.

Another 9 byte solution

K (oK), 15 14 bytes
{(x,x)#1,2_&x}

Try it online!
Adapted from @Zacharý's APL answer.

2_&x generate x-2 copies of zero
1, prepend a one
(x,x) duplicate x
(...)#... reshape into a x-by-x matrix

CJam, 18 bytes
qi__))'#*\((S**/N*

Try it online!
Joins n+2 hash characters together by n-2 spaces, then splits into n-length groups and joins by newline.