| Bytes | Lang | Time | Link |
|---|---|---|---|
| 065 | Python | 250627T051413Z | G B |
| 096 | Swift 6 | 250626T145746Z | macOSist |
| 058 | Ruby | 250626T065806Z | G B |
| 075 | JavaScript Node.js | 250625T045300Z | l4m2 |
| 076 | Python 3 | 250624T103820Z | Jitse |
| 017 | 05AB1E | 250625T080807Z | Kevin Cr |
| 070 | Python | 250625T054033Z | Albert.L |
| 160 | Google Sheets | 250624T181614Z | doubleun |
| 019 | Jelly | 250624T180449Z | Jonathan |
| 301 | Python3 | 250624T185000Z | Ajax1234 |
| 020 | Charcoal | 250624T151142Z | Neil |
Python, 65 bytes
lambda a,p:a//(w:=int((p+(p*p-16*a)**.5)/4))*('#'*w+'\n')+a%w*'#'
How?
Port of my Ruby answer
Swift 6, 96 bytes
{a,p in{$0($0("#",0+a/$1)+"\n",$1)+$0("#",a%$1)}({String.init}(),(1...).first{a<=$0*(p/2-$0)}!)}
A port of @AlbertLang's answer, sans recursion.
Ruby, 70 58 bytes
->a,p{[?#*p=((p+(p*p-16*a)**0.5)/4).to_i]*(a/p)+[?#*a%=p]}
How
The perimeter of the shape will be the same as the perimeter of the enclosing rectangle. We search for the widest rectangle with the given perimeter and area at least a.
JavaScript (Node.js), 75 bytes
A=>P=>[1,...Array(P-2>>2)].map((_,i,z)=>z.map(j=>!(1+i>P/4|i*!j&&A--<P/2)))
-6 bytes Weird Glyphs
Python 3, 76 bytes
def f(a,p):
i=h=p//4
while i:i-=1;print(('#'*(a-h-~-p//4*i)+'#')[:p+2>>2])
A perimeter p can be achieved by placing all squares in a partially filled rectangle with size floor(p/4) by ceil(p/4).
-2 bytes thanks to Arnauld
-2 bytes thanks to Jonathan Allan
-2 bytes thanks to xnor
05AB1E, 17 bytes
4÷DŠ-‚'#×`¹<4÷ä`»
Inputs in the order \$perimeter,area\$.
Port of @Neil's Charcoal answer, which in turn is based on @Jitse's observations, so make sure to upvote both of those answers as well! (Outputs 90 degrees flipped in comparison, though.)
Try it online or verify all test cases.
Explanation:
# E.g. inputs p=12,a=6
4÷ # Integer-divide the first (implicit) input-perimeter by 4
# STACK: 3
D # Duplicate that value
# STACK: 3, 3
Š # Triple-swap with the second (implicit) area
# STACK: 3, 6, 3
- # Subtract the perimeter//4 from the area
# STACK: 3, 3
‚ # Pair it together with the duplicated perimeter//4
# STACK: [3,3]
'#× '# Convert each to strings with that many "#"
# STACK: ["###","###"]
` # Pop and push both strings to the stack again
# STACK: "###", "###"
¹< # Push the first input-perimeter, and decrease it by 1
# STACK: "###", "###", 11
4÷ # Integer-divide that also by 4
# STACK: "###", "###", 2
ä # (Try to) split the top string into that many equal-sized parts
# STACK: "###", ["##","#"]
` # Pop and push all parts to the stack
# STACK: "###", "##", "#"
» # Join all strings on the stack by newlines
# STACK: "###\n"
# "##\n"
# "#"
# (after which the result is output implicitly)
Python, 70 bytes
f=lambda a,c,w=1:a>w*(v:=c//2-w)and f(a,c,w+1)or(("\n"+v*"#")*w)[:a+w]
Faulty Python, 70 bytes
f=lambda a,c,w=1:a>w*(c//2-w)and f(a,c,w+1)or(a//w*"#"+"\n")*w+a%w*"#"
Thanks to @doubleunary for spotting.
Tries different rectangular layouts until it finds a working one.
Google Sheets, 160 bytes
=let(_,lambda(x,y,rept(join("
",rept("#",y)&"
"),x)),w,ceiling(B1/4),h,int(B1/4),l,int(A1/w),s,h-l,m,l*w+s-A1,b,s-(m<0),_(l-(m>0),w)&_(abs(m),w-(b=0)-1)&_(b,1))
Put \$a\$ in cell A1, \$p\$ in B1, and the formula in C1.
Uses Jitse's dimensions. There are two inline line breaks in the lambda.

Ungolfed:
=let(
block_, lambda(x, y, rept(join(char(10), rept("#", y) & char(10)), x)),
width, ceiling(B1 / 4),
height, floor(B1 / 4),
numLongRows, floor(A1 / width),
numShortRows, height - numLongRows,
numMidRows, numLongRows * width + numShortRows - A1,
block_(numLongRows - (numMidRows > 0), width) &
block_(abs(numMidRows), width - (numShortRows - (numMidRows < 0) = 0) - 1) &
block_(numShortRows - (numMidRows < 0), 1)
)
Jelly, 19 bytes
ŒṗL,`jNƲạƝS⁼ʋƇṪ”#ẋY
A dyadic Link that accepts the area on the left and the perimeter on the right and yields a list of characters, or a full program that prints to stdout.
Try it online! Or see the test-suite.
How?
ŒṗL,`jNƲạƝS⁼ʋƇṪ”#ẋY - Link: Area; Perimeter
Œṗ - integer partitions of {Area}
Ƈ - keep those for which:
ʋ - last four links as a dyad - f(Partition, Perimeter)
Ʋ - last four links as a monad - f(Partition):
L - length of {Partition}
,` - pair with itself -> [L, L]
N - negate {Partition}
j - {[L, L]} join {negated Partition}
ạƝ - absolute differences of the neighbours in {that}
S - sum {these}
⁼ - is {that} equal to {Perimeter}?
Ṫ - tail of {that} (one valid partition or 0)
”#ẋ - repeat '#' {those} many times
Y - join {those} with newline characters
- (if a full program: implicit print)
Python3, 301 bytes
Naive approach.
E=enumerate
def f(a,p):
q=[(a-i,[[1]*i])for i in range(a,0,-1)]
for a,b in q:
D={(x,y)for x,r in E(b)for y,v in E(r)if v}
if 0==a and sum((x+X,y+Y)not in D for X,Y in[(1,0),(-1,0),(0,1),(0,-1)]for x,y in D)==p:return b
q+=[(a-i,b+[[0]*(len(b[0])-i)+[1]*i])for i in range(1,min(a,len(b[0]))+1)]
Charcoal, 20 bytes
G↑÷N⁴#M→⪪×#⁻NLKA÷⊖θ⁴
Try it online! Link is to verbose version of code. Takes the perimeter as the first argument and the area as the second. Assumes the perimeter is even. Explanation: Uses @Jitse's observation that the perimeter can be gained from a partial rectangle that then is filled to the appropriate area.
G↑÷N⁴#M→
Integer divide the perimeter by 4 and draw that many #s upwards, then move right.
⪪×#⁻NLKA÷⊖⊖θ⁴
Input the area, subtract the count of #s output so far, then wrap the rest to the the width of integer dividing the decremented perimeter by 4.