Информация об изменениях

Сообщение Re[5]: Детская задачка для скучающих от 06.01.2017 21:21

Изменено 06.01.2017 22:23 kov_serg

Re[5]: Детская задачка для скучающих
Здравствуйте, vdimas, Вы писали:

_>>Вообще-то получается всего два неравенства для одной переменной.

V>Не получается "всего два".
V>Я не вижу в этих неравенствах формулы вычисления угла a.
Странно, почему я вижу

V>Собсно, твои неравенства эквивалентны (математически, после подстановок) моим:

Ясен пень эквивалентны. Но решение в такой системе координат проще.

V>Но это не есть решение задачи, это всё еще формулировка/уточнение условия. ))

V>Решение — это найти "угол вписывания" одного прямоугольника в другой и проверить данное условие.
Если вам нужен угол то смотрите
  полное решение неравенства

d2*sin(f2)*sin(a) + d2*cos(f2)*cos(a) <= d1*cos(f1)
d2*sin(f2)*cos(a) + d2*cos(f2)*sin(a) <= d1*sin(f1)
0 < f1 < pi/2
0 < f2 < pi/2
0 <= a <= p/2

Переобразуем
cos(a-f2) <= q1 , q1=d1/d2*cos(f1)
sin(a+f2) <= q2 , q2=d1/d2*sin(f1)

замена переменных
a1=d1*sin(f1)
b1=d1*cos(f1)
a2=d2*sin(f2)
b2=d2*cos(f2)

одна неизвестная a — угол поворота второго прямоугольника относительно первого

function find_angles(d1,f1,d2,f2)
    local p2,r,rs,q1,q2=0.5*math.pi,{},{}
    q1=d1/d2*math.cos(f1)
    if q1<=1 then r[#r+1]={ f2, math.acos(q1) } end
    q2=d1/d2*math.sin(f1)
    if q2<=1 then r[#r+1]={ p2-f2, math.acos(q2) } end
    local function rgn(r1,r2) if r1<=r2 then rs[#rs+1]={r1,r2} end end
    if #r==0 then rs={ {0,p2} } 
    else 
        if #r==2 then
            if r[1][1]>r[2][2] then r={ r[2],r[1] } end
            if r[1][1]+r[1][2]>=r[2][1]-r[2][2] then
                r={{ 0.5*(r[1][1]-r[1][2]+r[2][1]+r[2][2]),
                     0.5*(r[2][1]+r[2][2]-(r[1][1]-r[1][2])) }}
            end
        end
        if #r==1 then
            rgn(0,r[1][1]-r[1][2])
            rgn(r[1][1]+r[1][2],p2)
        else
            rgn(0,r[1][1]-r[1][2])
            rgn(r[1][1]+r[1][2],r[2][1]-r[2][2])
            rgn(r[2][1]+r[2][2],p2)
        end
    end
    return rs
end

find_angles возвращает все решения (допустимые диапазоны) для угла a (границы включаются)

_>>Вот код решения на скорую руку
V>Код решения не соответствует приведенным неравенствам.
Точно ошибся. Посыпает голову пеплом.
Вот правильный вариант
#!/usr/bin/lua

function rect_fit(a1,b1,a2,b2)
    local d1,f1=math.sqrt(a1*a1+b1*b1), math.atan2(a1,b1)
    local d2,f2=math.sqrt(a2*a2+b2*b2), math.atan2(a2,b2)
    local function can_fit(d1,f1,d2,f2)
        local p2,r,rs,q1,q2=0.5*math.pi,{}
        q1=d1/d2*math.cos(f1); if q1<=1 then r[1]={ f2, math.acos(q1) } end
        q2=d1/d2*math.sin(f1); if q2<=1 then r[#r+1]={ p2-f2, math.acos(q2) } end
        rs=(#r==0) or (#r==1 and ( r[1][1]>=r[1][2] or r[1][1]+r[1][2]<=p2 ))
        if #r==2 then 
            if r[1][1]>r[2][2] then r={ r[2],r[1] } end
            rs=math.min(r[1][1]-r[1][2],r[2][1]-r[2][2])>=0
            or math.max(r[2][1]+r[2][2],r[1][1]+r[1][2])<=p2
            or r[1][1]+r[1][2]<=r[2][1]-r[2][2]
        end
        return rs
    end
    return can_fit(d1,f1,d2,f2)
end

function check_list(list)
    for k,v in pairs(list) do
        local r=rect_fit(v.a1,v.b1,v.a2,v.b2) and 'possible' or 'impossible'
        print(string.format("[%.3f * %.3f] <-- [%.3f * %.3f] - %s",v.a1,v.b1,v.a2,v.b2,r))
    end
end

check_list
{ 
    { a1=2,b1=2, a2=1,b2=1 },
    { a1=1,b1=1, a2=2,b2=2 },
    { a1=5,b1=5, a2=5.5,b2=1 },
}

Выхлоп
[2.000 * 2.000] <-- [1.000 * 1.000] - possible
[1.000 * 1.000] <-- [2.000 * 2.000] - impossible
[5.000 * 5.000] <-- [5.500 * 1.000] - possible
Re[5]: Детская задачка для скучающих
Здравствуйте, vdimas, Вы писали:

_>>Вообще-то получается всего два неравенства для одной переменной.

V>Не получается "всего два".
V>Я не вижу в этих неравенствах формулы вычисления угла a.
Странно, почему я вижу

V>Собсно, твои неравенства эквивалентны (математически, после подстановок) моим:

Ясен пень эквивалентны. Но решение в такой системе координат проще.

V>Но это не есть решение задачи, это всё еще формулировка/уточнение условия. ))

V>Решение — это найти "угол вписывания" одного прямоугольника в другой и проверить данное условие.
Если вам нужен угол то смотрите
  полное решение неравенства

d2*sin(f2)*sin(a) + d2*cos(f2)*cos(a) <= d1*cos(f1)
d2*sin(f2)*cos(a) + d2*cos(f2)*sin(a) <= d1*sin(f1)
0 < f1 < pi/2
0 < f2 < pi/2
0 <= a <= p/2

Переобразуем
cos(a-f2) <= q1 , q1=d1/d2*cos(f1)
sin(a+f2) <= q2 , q2=d1/d2*sin(f1)

замена переменных
a1=d1*sin(f1)
b1=d1*cos(f1)
a2=d2*sin(f2)
b2=d2*cos(f2)

одна неизвестная a — угол поворота второго прямоугольника относительно первого

function find_angles(d1,f1,d2,f2)
    local p2,r,rs,q1,q2=0.5*math.pi,{},{}
    q1=d1/d2*math.cos(f1)
    if q1<=1 then r[#r+1]={ f2, math.acos(q1) } end
    q2=d1/d2*math.sin(f1)
    if q2<=1 then r[#r+1]={ p2-f2, math.acos(q2) } end
    local function rgn(r1,r2) if r1<=r2 then rs[#rs+1]={r1,r2} end end
    if #r==0 then rs={ {0,p2} } 
    else 
        if #r==2 then
            if r[1][1]>r[2][2] then r={ r[2],r[1] } end
            if r[1][1]+r[1][2]>=r[2][1]-r[2][2] then
                r={{ 0.5*(r[1][1]-r[1][2]+r[2][1]+r[2][2]),
                     0.5*(r[2][1]+r[2][2]-r[1][1]+r[1][2]) }}
            end
        end
        if #r==1 then
            rgn(0,r[1][1]-r[1][2])
            rgn(r[1][1]+r[1][2],p2)
        else
            rgn(0,r[1][1]-r[1][2])
            rgn(r[1][1]+r[1][2],r[2][1]-r[2][2])
            rgn(r[2][1]+r[2][2],p2)
        end
    end
    return rs
end

find_angles возвращает все решения (допустимые диапазоны) для угла a (границы включаются)

_>>Вот код решения на скорую руку
V>Код решения не соответствует приведенным неравенствам.
Точно ошибся. Посыпает голову пеплом.
Вот правильный вариант
#!/usr/bin/lua

function rect_fit(a1,b1,a2,b2)
    local d1,f1=math.sqrt(a1*a1+b1*b1), math.atan2(a1,b1)
    local d2,f2=math.sqrt(a2*a2+b2*b2), math.atan2(a2,b2)
    local function can_fit(d1,f1,d2,f2)
        local p2,r,rs,q1,q2=0.5*math.pi,{}
        q1=d1/d2*math.cos(f1); if q1<=1 then r[1]={ f2, math.acos(q1) } end
        q2=d1/d2*math.sin(f1); if q2<=1 then r[#r+1]={ p2-f2, math.acos(q2) } end
        rs=(#r==0) or (#r==1 and ( r[1][1]>=r[1][2] or r[1][1]+r[1][2]<=p2 ))
        if #r==2 then 
            if r[1][1]>r[2][2] then r={ r[2],r[1] } end
            rs=math.min(r[1][1]-r[1][2],r[2][1]-r[2][2])>=0
            or math.max(r[2][1]+r[2][2],r[1][1]+r[1][2])<=p2
            or r[1][1]+r[1][2]<=r[2][1]-r[2][2]
        end
        return rs
    end
    return can_fit(d1,f1,d2,f2)
end

function check_list(list)
    for k,v in pairs(list) do
        local r=rect_fit(v.a1,v.b1,v.a2,v.b2) and 'possible' or 'impossible'
        print(string.format("[%.3f * %.3f] <-- [%.3f * %.3f] - %s",v.a1,v.b1,v.a2,v.b2,r))
    end
end

check_list
{ 
    { a1=2,b1=2, a2=1,b2=1 },
    { a1=1,b1=1, a2=2,b2=2 },
    { a1=5,b1=5, a2=5.5,b2=1 },
}

Выхлоп
[2.000 * 2.000] <-- [1.000 * 1.000] - possible
[1.000 * 1.000] <-- [2.000 * 2.000] - impossible
[5.000 * 5.000] <-- [5.500 * 1.000] - possible