Pull to refresh
1083
0.9
Михаил Сваричевский @BarsMonster

Терминатор кремния

Send message

RISC-V мини-ноутбук: Lichee Console 4A — обзор, тесты и сложности

Level of difficulty Easy
Reading time 7 min
Views 13K

Мне всегда нравились маленькие ноутбуки (нетбуки?) и телефоны - но почему-то производители их не взлюбили, и соревнуются у кого больше. Маленькие и микро-ноутбуки остались зачастую только на ebay - например UMPC от Sony, которые до сих пор стоят 300$ и выше. Недавно начали появляться портативные системы основанные на Raspberry Pi/CM4 - в особенности красиво все у clockwork, но все они не складываются книжкой. Так что когда летом 2023-го Sipeed анонсирована Lichee Console 4A, да еще и на RISC-V процессоре - я немедленно его заказал, и наконец в начале января он до меня доехал. Результаты тестирования и обнаруженные сложности/проблемы - ниже.

Читать далее
Total votes 59: ↑58 and ↓1 +57
Comments 62

Делаем 10-минутную задачу за 2 часа с помощью ChatGPT

Level of difficulty Easy
Reading time 5 min
Views 72K

Все мы видели много статей, где с помощью AI-инструментов за минуты выполняется работа, на которую раньше мог легко уйти день. Особенно впечатляют примеры, где работа (успешно) идет вне зоны компетенции человека (т.е. когда AI позволяет делать то, что человек в принципе один сделать не мог бы). Но сегодня у меня получился несколько другой случай:

Читать далее
Total votes 74: ↑70 and ↓4 +66
Comments 35

Гикпорн наручных кварцевых часов «Луч» — и немного оверклокинга

Reading time 3 min
Views 38K
Некоторые вещи, к которым мы совсем привыкли, а иногда считаем очень устаревшими и простыми — при ближайшем рассмотрении могут быть гораздо сложнее, чем кажется.

На мой взгляд самыми неожиданно сложными, пусть и кажущимися устаревшими вещами являются кварцевые часы и пленочные фотоаппараты. Доступными их сделали сотни лет развития мирового индустриального производства и многие миллиарды потраченные на R&D.

Кварцевыми часами в этот раз мы и займемся. В качестве пациента — наручные часы Луч Белорусского производства, которые мне подарили в незапамятные времена.
Total votes 142: ↑142 and ↓0 +142
Comments 38

Внутренности SDR чипа AD9361 — когда микроэлектроника выгоднее наркоторговли

Reading time 5 min
Views 54K
Когда в 2013 году Analog Devices выпустила SDR трансивер AD9361 — случилась настоящая революция в цифровой радиосвязи. SDR были и раньше, но теперь в одном чипе можно было получить все: 2 канала на прием и 2 на передачу (с набортными 12-бит ЦАП и АЦП) с шириной канала до 56МГц, локальные генераторы и радиотракт — для работы в диапазоне от 70 (на передачу от 47) до 6000Мгц. На AD9361 «из коробки» можно реализовать почти любой цифровой приемопередатчик, за исключением наверное только UWB и начинающего набирать популярность диапазона 60ГГц (но там без аппаратной многоэлементной ФАР все равно делать почти нечего). Остается лишь добавить источник/приемник данных (пока это обычно FPGA), внешние фильтры и LNA/PA, если задача того требует.

Мне наконец удалось посмотреть, что у него внутри, и — попробовать взглянуть на финансовую сторону производства действительно инновационной микроэлектроники с высокой добавленной стоимостью.

Читать дальше →
Total votes 77: ↑77 and ↓0 +77
Comments 48

Смотрим внутренности отечественного 28нм MIPS процессора — Baikal-T1

Reading time 2 min
Views 79K
Думаю многие уже слышали про реализованный московскими разработчиками Байкал Электроникс процессор Байкал-Т1 — с двумя ядрами Imagination Technologies P5600 MIPS 32 r5 и набортным 10GbE. Байкал оказался первым, кто реализовал в кремнии это ядро.

Терзал этот процессор я с перерывами больше года — но наконец под катом могу поделиться результатами.
Читать дальше →
Total votes 130: ↑128 and ↓2 +126
Comments 76

Автомобильные HUD в общем и WayRay Navion в частности

Reading time 7 min
Views 22K
Начиная с конца 80-х в машинах подороже начали появляться HUD (Head-up display) – прозрачные дисплеи, которые водитель наблюдает, глядя вперед через лобовое стекло. А еще ранее (незадолго до начала второй мировой войны), в рудиментарном виде – на самолетах, для отображения прицельной марки без параллакса с дальнейшим развитием до современных HUD.

Технологии создания HUD всегда были на острие прогресса: начиная от простых фиксированных прицельных марок из проволоки или нарисованных на стекле, до CRT дисплеев, затем ЖК и наконец DLP и голографических, с лазерной подсветкой. Именно тут, когда стали коммерчески доступны все необходимые компоненты и технологии — появился WayRay со своим продуктом Navion – каких-нибудь 7 лет назад сделать все это было бы просто невозможно: не было ни материалов, ни подходящих лазеров, ни пространственных модуляторов, да и электроника обошлась бы на порядок дороже.
Читать дальше →
Total votes 53: ↑50 and ↓3 +47
Comments 59

Первый 90нм продукт из Микрона под микроскопом — 16 Mibit SRAM

Reading time 2 min
Views 51K
Много громких заявлений вокруг Микрона на просторах Рунета — но не часто их удается проверить на практике. Каков он, 90нм от Микрона? Благодаря анонимному читателю удалось получить образец 90нм микросхемы, произведенной на Микроне — 1663РУ1, 16Мбит статической памяти. Не стану томить — 90нм там таки есть!

Читать дальше →
Total votes 94: ↑93 and ↓1 +92
Comments 14

Реверс-инжиниринг мерцающего светодиода (+RGB)

Reading time 3 min
Views 47K
1.5 года назад на Хабре писали о попытке реверс-инжениринга случайно мерцающего светодиода. Тогда попытки проанализировать паттерны мерцания светодиода как черного ящика окончательным успехом не увенчались — однако было установлено распределение скважностей модуляции яркости, и был написан эмулятор. За прошедшее время разные группы вскрывали мерцающие светодиоды — и об их работе стало известно несколько больше. Наконец, дошли до них руки и у меня.

За прошедшее время обнаружилось, что кристаллов «случайного моргания» — довольно много разновидностей. Фотографии и размышления авторов на тему принципа работы аналогичных кристаллов — siliconpr0n.org, cpldcpu.wordpress.com, hackaday.com. Удивляет то, что мало того, что кто-то предметно занимается разработкой и массовым производством такой казалось бы незначительной вещи как мерцающий светодиод — там еще есть и прогресс/конкуренция!
Читать дальше →
Total votes 52: ↑50 and ↓2 +48
Comments 14

Реверс-инжениринг КР580ВМ80А / i8080 завершен

Reading time 2 min
Views 166K
Рад сообщить, что реверс-инжениринг КР580ВМ80А полностью завершен. Получена полная принципиальная схема и Verilog-модель. В невероятно короткие сроки схему восстановил Vslav 1801BM1 (1801ВМ1@gmail.com).

Оказалось, в КР580ВМ80А ровно 4758 транзисторов (а не 6000 или 4500, как иногда ошибочно упоминают).

Топология КР580ВМ80А похожа, но не идентична i8080. Тем не менее, отличий в реализации опкодов КР580ВМ80А не было обнаружено.

Verilog-модель успешно прошла зубодробительный тест качества симуляции и как Verilog-модель, и как FPGA заменяя реальный КР580ВМ80А в "Специалисте".

Файлы: Главная модель Verilog, схема, Полный пакет файлов.
Читать дальше →
Total votes 159: ↑157 and ↓2 +155
Comments 95

Гикпорн 4 — продолжаем вскрывать микросхемы: БК0010, MEMS гироскоп и немного Роснано

Reading time 4 min
Views 58K
С момента публикации предыдущего поста с вскрытыми микросхемами прошло пол года — пора рассказать, что удалось увидеть нового. Для тех кто пропустил первые 3 серии — вот раз, два, три.

Toshiba TCD1201D — линейный монохромный CCD светочувствительный сенсор из 2048 элементов. Датчики такого типа применяются в факсах, считывателях штрих-кодов и даже на спутниках, фотографирующих землю. Сами светочувствительные элементы — в линии в центре кристалла. Накопленный за время облучения светом заряд постепенно «сдвигается» к краю кристалла двухфазным тактовым сигналом, где он усиливается — и далее уже может быть оцифрован, получится 1 строчка изображения.

Читать дальше →
Total votes 156: ↑154 and ↓2 +152
Comments 20

Результаты и обсуждение майского хабрасоревнования: делаем свой ГЛОНАСС

Reading time 16 min
Views 14K
Итак, настало время подвести итоги прошедшего майского хабрасоревнования. Было прислано 49 решений, удовлетворяющих требованиям по оформлению и 8 решений вне конкурса (позже дедлайна, с ошибками оформления, на неверный адрес). Что-ж, посмотрим, кто что написал.

Хотя в обсуждении топика с самой задачей люди переживали, что самое компактное и самое быстрое решение — это разные вещи, оказалось что решение победителя lany — является и самым компактным, удовлетворяющим всем требованиям. Решение Frommi было вдвое компактнее, 863 байта — но не смогло пройти все тесты. Следующим шло решение ibessonov на 1613 байта — но оно внезапно показало большую ошибку на первом тесте.

Если у меня читатели не найдут ошибки, тройка победителей будет выглядеть так:

  1. lany — двойной победитель, 89.9448 баллов и самое компактное решение.
    Самый большой тест (2.4Гб) пройден за 0.61 секунду.
    Смотреть исходник
    //@lany
    public class G{java.io.InputStream I=System.in;int c,i=0,j,m,M;double[]S=new double[512],C=new double[512];byte[]P="111001100011101101".getBytes(),d=new byte[999999];double N=4.0678884e13,L=29.9792458,X,Y,q,F,G,H=1e99;S[]z;S f,g;class S{double x,y,r,q,R,Q;S(){x=new Double(l());y=new Double(l());try{I.read(d);I.skip(9000001);}catch(Exception e){}q=L*o()+L/2;Q=q*q;r=q-L;R=r*r;l();}int o(){int o=0,p;for(;;o+=10){for(p=0;p<18;p++)if(P[p]!=d[o+p*10])break;if(p==18){while(d[--o]>48);return o+1;}}}}void u(double X,double Y){if(X*X+Y*Y<N){double S=d(X,Y);if(S<H){H=S;F=X;G=Y;}}}double d(double x,double y){double q=0,Q=-1,X,Y;for(S s:z){X=x-s.x;Y=y-s.y;X=X*X+Y*Y;if(X>s.Q)q+=X-s.Q;else if(X<s.R)q+=s.R-X;else if(q==0){Y=Math.sqrt(X);Q*=Math.min(s.q-Y,Y-s.r)*.1;}}return q>0?q:Q;}void b(double r,double R){if(r+R>q){double d=Math.abs(r*r-R*R+q*q)/2/q,h=Math.sqrt(r*r-d*d),x=f.x+X*d,y=f.y+Y*d;u(x-Y*h,y+X*h);u(x+Y*h,y-X*h);}}String l(){char[]o=new char[99];int p=0,b;try{while((b=I.read())!=10)o[p++]=(char)b;}catch(Exception e){}return new String(o,0,p).trim();}public static void main(String[]a){new G();}G(){for(;i<512;i++){q=Math.PI*i/256;S[i]=Math.sin(q);C[i]=Math.cos(q);}c=new Short(l());z=new S[c];for(i=0;i<c;)z[i++]=new S();for(i=1;i<c&&H>0;i++)for(j=0;j<i&&H>0;j++){f=z[i];g=z[j];X=g.x-f.x;Y=g.y-f.y;q=Math.sqrt(X*X+Y*Y);X/=q;Y/=q;b(f.q,g.q);b(f.r,g.q);b(f.q,g.r);b(f.r,g.r);}double x=F,y=G,r=d(x,y),t=r<1e10?1e3:3e6,u,v,w,R;while(t>.1&&(i++<999||r>0)){R=r;X=x;Y=y;for(M=4;M<513&&R==r;M*=2){for(m=0;m<M;m++)if(M<5||m%2>0){j=m*512/M;u=x+S[j]*t;v=y+C[j]*t;if(u*u+v*v<N){w=d(u,v);if(w<R){X=u;Y=v;R=w;}}}}if(R<r){x=X;y=Y;r=R;}else t/=2;}System.out.println(x+" "+y);}}
  2. @AKashta — 86.9558 балла, на самом большом тесте вдвое быстрое lany, но немного проиграл по точности.
    Смотреть исходник
    //@AKashta
    
    import java.io.*;
    import java.util.ArrayList;
    
    public class Main {
    
        public static final boolean ADVANCED_MODE = true;
        public static final int MAX_POINTS = 50;
        public static final double PRECISION = 30;
        public static final int THRESHOLD = 300;
    
        public static final String START_TOKEN = "111001100011101101";
        public static final long DATA_LENGTH = 10000000;
        public static final long SPEED = 299792458;
        public static final long EARTH_R = 6378000;
        public static final long MIN_SAT_POS = 10000000;
        public static final long MAX_SAT_POS = 20000000;
        public static final int MIN_OFFSET = (int)((MIN_SAT_POS - EARTH_R) * DATA_LENGTH / SPEED);
        public static final int MAX_OFFSET = (int)((MAX_SAT_POS + EARTH_R) * DATA_LENGTH / SPEED);
    
        public static void main(String args[ ]) {
            //long startTime = System.currentTimeMillis();
            try {
                DataInputStream in = new DataInputStream(System.in);
                DataReader reader = new DataReader(in);
                Point result = null;
    
                int q = reader.readInt();
                ArrayList<Circle> sats = new ArrayList<Circle>(q);
                for(int i = 0; i < Math.min(q, MAX_POINTS); i++) {
                    double x = reader.readDouble();
                    double y = reader.readDouble();
                    int offset = reader.readOffset();
    
                    double radius = ((double)SPEED / DATA_LENGTH * offset);
    
                    sats.add(new Circle(new Point(x, y),  radius));
                }
    
                if(sats.size() == 2) {
                    ArrayList<Point> points = sats.get(0).intersect(sats.get(1));
                    for(Point p : points) {
                        result = p;
                        break;
                    }
                }  else {
                    if(ADVANCED_MODE) {
                        result = advancedCalc(sats);
                    } else {
                        result = simpleCalc(sats);
                    }
                }
    
                System.out.println(result.x + " " + result.y);
                //long time = (System.currentTimeMillis() - startTime);
                //System.out.println("Time: " + time);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    
        public static Point findRefPoint(ArrayList<Circle> sats){
            ArrayList<Point> points = new ArrayList<Point>();
            for(int i = 0; i < 2; i++) {
                for(int j = i + 1; j < 3; j++) {
                    points.addAll(sats.get(i).intersect(sats.get(j)));
                }
            }
    
            Point p0 = null, p1 = null, p2 = null;
            for(Point p : points) {
                for(Point t : points) {
                    if(p1 == null && t != p && p.distance(t) < THRESHOLD){
                        p1 = t;
                        continue;
                    }
                    if(p1 != null && t != p && t != p1 && p.distance(t) < THRESHOLD){
                        p2 = t;
                        break;
                    }
                }
                if(p1 != null && p2 != null) {
                    p0 = p;
                    break;
                } else {
                    p1 = null;
                    p2 = null;
                }
            }
            return new Point((p0.x + p1.x + p2.x) / 3, (p0.y + p1.y + p2.y) / 3);
        }
    
        public static Point advancedCalc(ArrayList<Circle> sats){
            ArrayList<Point> allPoints = new ArrayList<Point>();
            for(int i = 0; i < sats.size() - 1; i++) {
                for(int j = i + 1; j < sats.size(); j++) {
                    allPoints.addAll(sats.get(i).intersect(sats.get(j)));
                }
            }
    
            int count = 0;
            double sumX = 0;
            double sumY = 0;
    
            for(Point p : allPoints) {
                boolean containsInAll = true;
                for (Circle sat : sats){
                    if(!sat.hasPoint(p)) {
                        containsInAll = false;
                        break;
                    }
                }
                if(containsInAll) {
                    count++;
                    sumX += p.x;
                    sumY += p.y;
                }
            }
            return new Point(sumX / count, sumY / count);
        }
    
        public static Point simpleCalc(ArrayList<Circle> sats){
            int count = 0;
            double sumX = 0;
            double sumY = 0;
    
            Point refPoint = findRefPoint(sats);
            for(int i = 0; i < sats.size() - 1; i++) {
                for(int j = i + 1; j < sats.size(); j++) {
                    for(Point p : sats.get(i).intersect(sats.get(j))) {
                        if(refPoint.distance(p) < THRESHOLD) {
                            count++;
                            sumX += p.x;
                            sumY += p.y;
                        }
                    }
                }
            }
            return new Point(sumX / count, sumY / count);
        }
    
        public static class DataReader {
            private DataInputStream _in;
    
            public DataReader(DataInputStream in){
                _in = in;
            }
    
            public int readOffset() throws Exception {
                byte firstByte = _in.readByte();
                int offset = 1;
                while( _in.readByte() == firstByte) {
                    offset++;
                }
                int needToSkip = ((MIN_OFFSET - offset) / 10) * 10;
                _in.skipBytes(needToSkip);
                offset += needToSkip;
    
                byte[] buffer = new byte[MAX_OFFSET - offset];
                _in.read(buffer);
                _in.skipBytes((int) DATA_LENGTH - offset - buffer.length - 1 + 2);
    
                StringBuilder sb = new StringBuilder(buffer.length / 10);
                for(int i = 0; i < buffer.length / 10; i++ ){
                    sb.append((char) buffer[i * 10]);
                }
    
                int index = sb.indexOf(START_TOKEN)* 10;
    
                return index + offset;
            }
    
            public String readLine() throws Exception {
                StringBuilder sb = new StringBuilder();
                char c;
                while((c = (char)_in.readByte()) != '\r') {
                    sb.append(c);
                }
                _in.readByte(); // read '\n' char
                return  sb.toString();
            }
    
            public int readInt() throws Exception {
                String s = readLine();
                return Integer.parseInt(s);
            }
    
            public Double readDouble() throws Exception {
                String s = readLine();
                return Double.parseDouble(s);
            }
        }
    
        public static class Point {
            public double x;
            public double y;
    
            public Point(double x, double y) {
                this.x = x;
                this.y = y;
            }
    
            public double distance() {
                return Math.sqrt(x*x + y*y);
            }
    
            public double distance(Point p) {
                return Math.sqrt(Math.pow(x - p.x, 2) + Math.pow(y - p.y, 2));
            }
        }
    
        public static class Circle {
            public Point center;
            public double radius;
            public Circle(Point p, double r) {
                center = p;
                radius = r;
            }
    
            public ArrayList<Point> intersect(Circle c) {
                ArrayList<Point> result = new ArrayList<Point>();
    
                double dx = c.center.x - center.x;
                double dy = c.center.y - center.y;
                double d = Math.sqrt((dy * dy) + (dx * dx));
    
                if(d < Math.abs(radius - c.radius)) {
                    if(radius < c.radius)
                        radius += Math.abs(radius - c.radius) - d + 0.1;
                    else
                        c.radius += Math.abs(radius - c.radius) - d + 0.1;
                }
                if (d > (radius + c.radius)) {
                    double add = (d - (radius + c.radius))/ 2.0 + 0.1;
                    radius += add;
                    c.radius += add;
                }
    
                if (d > (radius + c.radius) || d < Math.abs(radius - c.radius)) {
                    //System.out.println("do not intersect");
                    return result;
                }
    
                double a = ((radius * radius) - (c.radius * c.radius) + ( d *d)) / (2.0 * d);
    
                Point p2 = new Point(center.x + (dx * a/d), center.y + (dy * a/d));
    
                double h = Math.sqrt((radius * radius) - (a*a));
                double rx = -dy * (h/d);
                double ry = dx * (h/d);
    
                Point p = new Point(p2.x + rx, p2.y + ry);
                if(p.distance() <= EARTH_R) {
                    result.add(p);
                }
                p = new Point(p2.x - rx, p2.y - ry);
                if(p.distance() <= EARTH_R) {
                    result.add(p);
                }
    
                return result;
            }
    
            public boolean hasPoint(Point p) {
                double d = center.distance(p);
                return Math.abs(d - radius) <= PRECISION;
            }
        }
    }
  3. @habrunit — 83.9379 балла, буквально вырвал призовое место из рук Staker.
    Смотреть исходник
    //@habrunit
    //package olimp;
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.UnsupportedEncodingException;
    import java.security.NoSuchAlgorithmException;
    import static java.lang.Math.*;
    
    public class Olimp {
    	private static int cash[]={0xc0001200,0x10818201,0x51feba02,0x1483a003,0xb6ffc304,0x8d953105,0x1b2e7e06,0x780a707,0x59041a08,0x283b1c09,0x5818430a,0xc13b950b,0x3921ed0c,0x599b60d,0x99c8400e,0x2612640f,0xb7b0ca10,0x8c17d11,0xd35fda12,0x96863f13,0xca7ea414,0x90875415,0xc860e416,0x6239c317,0x9f39d418,0xccc48419,0x3f43d11a,0x9e366d1b,0x37fc9a1c,0x103bd91d,0xe96c501e,0x80ccf81f,0x602aca20,0xed28b721,0xcedf2d22,0xd2da9e23,0x93574024,0xebba4125,0x77fcc26,0xf8eb1a27,0xc6e09728,0x58dfe129,0xc776642a,0x6688342b,0x102a252c,0xedec802d,0xdf737f2e,0x4b5b402f,0x9c29fb30,0x93300a31,0xc30d2b32,0xabe73633,0x61f4fa34,0xf4334c35,0xd27b8a36,0xf7b63e37,0x602d9038,0x2e8aff39,0x4e62003a,0xc489143b,0x4e5ed53c,0x57a46f3d,0xf6630b3e,0xb392f53f,0xba827340,0x5b9b7e41,0x3e9d1f42,0x29b2c743,0x47f8644,0xe4d74745,0xf1263046,0x3d44e47,0xb1905148,0xd079d849,0x66f16d4a,0x281ff94b,0x4cbc284c,0xe364e94d,0x5fda1a4e,0x4628d24f,0x47d17d50,0x53ca2751,0x6738c52,0x2a1c9653,0xcdab0454,0x7429e855,0x91c38556,0xb3c8ab57,0xa98cb258,0x26151d59,0x5525b75a,0xd955c75b,0x51c3475c,0x8350855d,0x1c30b65e,0x70339d5f,0x78a88460,0x4cc2a361,0x12464c62,0x5a34b63,0x3fee8864,0xa8633565,0x3e23d766,0xf8cd5767,0x52432068,0x9cae0969,0x63aa1d6a,0x8742826b,0x75e67b6c,0x2ef696d,0x25006d6e,0x89daa76f,0xbbb71870,0x2faca571,0x71374172,0x9b818673,0xa0de6274,0x29326075,0xb2401776,0x8edcb677,0x7a265378,0x87dd7779,0xb726ce7a,0x99f0397b,0x81a8967c,0x97d0437d,0xc9147e,0x27a1a17f,0xabd65680,0xc405e681,0xc0107482,0xe63b7783,0x16d43984,0x37c8e085,0xc6f26286,0x151dac87,0x67c36588,0xe593b589,0x669e388a,0x5c46a68b,0xb822fe8c,0x6455d18d,0x54b49d8e,0x475edc8f,0xfa8a9690,0xa38c7d91,0xa25f6692,0x32b9a193,0x22bf7c94,0xa72cfb95,0xcaa48696,0x78639e97,0x5dca8798,0xe263e99,0x59c599a,0x855a4f9b,0x4e66949c,0x3a27d89d,0xca15ec9e,0xe443da9f,0xaeaea3a0,0xdc6cdca1,0xa3bb51a2,0xd0f12da3,0xfcd7cda4,0x959c62a5,0x9e276ca6,0x67caeca7,0xc36d51a8,0xe76712a9,0x95d4b5aa,0xe6b1a1ab,0x60979aac,0xae2d55ad,0xf73e82ae,0x87622af,0x55678db0,0xf3813ab1,0x66bd2ab2,0x640762b3,0xab7d25b4,0xce243ab5,0x565e39b6,0x9389fcb7,0xecb84db8,0x8da369b9,0x2b1138ba,0x1a1b3ebb,0xa6a40cbc,0x2659acbd,0xb90ac3be,0xbb61e9bf,0x17dc81c0,0xf9cb57c1,0x1f2c47c2,0x177c6ec3,0x68cb55c4,0x94648fc5,0xb6c33ec6,0x9e71ffc7,0x21d49c8,0x1c1f96c9,0x40fdf8ca,0x608471cb,0x90c71acc,0x83049fcd,0x31232bce,0xa755d0cf,0x2995fd0,0x8ef786d1,0xaf7ae2d2,0x49e5f9d3,0xb621d1d4,0xa30ef5d5,0x75e168d6,0x6fcb3d7,0xe83308d8,0x29c1ead9,0x6b000ada,0xf37c94db,0xe2884cdc,0x7f92e0dd,0x93836ade,0x633232df,0xe29bc4e0,0x8e761fe1,0x31a905e2,0xd46a41e3,0x159184e4,0xd3f654e5,0x6abdbde6,0x865f3be7,0x9f7c41e8,0xb6e13de9,0xae2525ea,0x62d6c9eb,0x271459ec,0x1a13ffed,0x173ed9ee,0x1d2edaef,0x44366bf0,0xc9928f1,0x3fb38bf2,0xdf3dacf3,0x1b5250f4,0xf5f486f5,0x6a7c18f6,0xfce055f7,0xde547ff8,0x35a76ef9,0x2d3666fa,0xa4ba58fb,0x83f9f6fc,0xedb424fd,0xcc4d8fe,0xe0f0baff};
    	private static int cashLen[]={0x328aa,0x6144d,0xb900e,0x3ef04,0x7a10,0xc65aa,0x85819,0x6acf,0x16e30,0x3c13e,0x95b7b,0xcdfba,0xdd3e0,0xbae88,0x1406b,0x2ae9a,0x7bf85,0x17d72,0x9e4cd,0x8e16a,0x754b6,0x68e5c,0xd4a89,0xd6904,0x501a8,0x496da,0x21606,0x3d080,0x98942,0x4f269,0x374f4,0x8f0af,0xa9be5,0xc74e5,0x1f782,0x3fe46,0xc0a16,0xc37da,0x8a462,0x31968,0x510eb,0x59a3c,0x19bf6,0xa4f9b,0xaf773,0xb15f4,0xc8424,0xe10f0,0xb80c2,0x97a00,0x3dfc2,0x90f31,0x94c38,0xf1440,0xa1294,0x6cb64,0xca2b1,0x9d58a,0x632d8,0x42c0c,0x112a4,0x56c76,0xf23e2,0xe8af6,0x93cf6,0x29016,0x848d6,0xac9aa,0xe2f62,0x7733a,0x4b561,0x48799,0xd3b4a,0xe5d49,0xcd078,0x80bce,0x1e84,0xe7bad,0x2dc60,0x5202c,0x10362,0x74574,0x40d88,0xb718,0x9b707,0x35670,0x13128,0xbfada,0x3b1fc,0xcfe57,0x41ccc,0xd59e,0xd2c03,0x67f1b,0x2eba2,0x8952,0xe4e0d,0xb06b4,0x7de08,0x1c9bc,0x57bb8,0x14fac,0xaba6b,0xd59c5,0x26250,0x6bc24,0xb7184,0x38436,0xee717,0x121e6,0x46916,0x9894,0xe019d,0x18cb4,0x1d8fe,0x53eb0,0x83998,0x52f6e,0x39379,0x337ec,0xa4059,0xc4724,0x6daa6,0x5a97e,0x726f0,0x66097,0x6f92a,0x717ae,0xa5ee4,0x73632,0x2348a,0x0,0xc289a,0x7ed4a,0xd784f,0x6e9e8,0x6238e,0xdb54c,0xbeb93,0x92db5,0x66fd8,0x9988a,0x4c4a0,0xe6c69,0x5f5c8,0xd1cb8,0x5b8c0,0x64212,0x1ba7a,0xf420,0x5e686,0xd878a,0xbcd0c,0x7086c,0xe9a3b,0xad8ec,0x54df2,0x5d744,0x763fa,0xe3ecf,0x8d22d,0xb6243,0x9f412,0x206c5,0x9a7c8,0x9c64c,0xcc12f,0x81b12,0x89520,0x96abc,0xe204a,0x365b2,0x7b045,0xa7d6,0x44a90,0xd0d84,0x4e325,0xb3485,0x29f58,0x55d34,0x459d3,0xb253c,0x4c4a,0x5b8c,0xda610,0xea98d,0x885de,0xc65a,0x69d9e,0xc9367,0x4a61c,0xa3117,0x8b3a4,0xd96c8,0x65154,0xde316,0x6ace0,0x3d08,0x5c803,0xbbdcd,0xb43bc,0xc565e,0xa0351,0xf33a7,0xa7d60,0x791be,0xdc4ad,0x280d4,0x1e840,0x2dc6,0x7827c,0xdf25d,0xa8ca8,0x91e73,0xf42,0x8fff1,0x47856,0x7cec6,0x243ce,0xe4de,0xb5305,0x82a53,0x2cd22,0x3472e,0x58afa,0xc195a,0xcb1ec,0xb9f48,0x8675a,0xae834,0xceef9,0xbdc52,0x2bddc,0x8769c,0x7a100,0x7fc91,0x8c2ea,0xa21d5,0x22548,0x3a2bc,0x6050b,0x1ab38,0xef5b9,0xaab26,0xeb8b3,0x15eee,0x43b4e,0x27192,0x2fae4,0xa6e29,0xec7fb,0x2530e,0x4d3e2,0xed769,0x30a26,0xf0568};
    	Circle circles[];
    	double kof=29.9792458;
    	// 
    	static InputStream in;
    	// 
    	final int maxLen10=10000000;
    	final int maxLen1=maxLen10/10;
    	final int maxLenB=16384;
    	// 
    	final byte buf[]=new byte[maxLenB];
    	int posBuf=0;
    	int lenBuf=0;
    	
    	public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException, FileNotFoundException, IOException {
    		
    //		Pset tests[]=new Pset[]{new Pset(-1.81683e+006,-1.74334e+006),new Pset(3.06932e+006, -2.59405e+006),new Pset(3420803.233, -1950298.548)};
    //		long t=System.currentTimeMillis();
    //
    //		for(int i=0;i<tests.length;i++){
    //			in=new FileInputStream("test"+(i+1)+".in");
    //			Pset answer=new Pset();
    //			new Olimp(answer);
    //			answer.printDlta(tests[i]);
    //		}
    //		System.out.println("end"+(System.currentTimeMillis()-t));
    
    
    
    		//in=new FileInputStream("test1.in");
    		in=System.in;
    		Pset answer=new Pset();
    		new Olimp(answer);
    		answer.print();
    		
    	}
    	
    	
    	double readDouble(){
    		while(isBR(buf[posBuf]))posBuf++;
    		int start=posBuf;
    		while(!isBR(buf[posBuf]))posBuf++;
    		String s=new String(buf,start,posBuf-start);
    		while(isBR(buf[posBuf]))posBuf++;
    		return Double.parseDouble(s);
    	}
    	static final boolean isBR(final byte val){
    		return val==13 || val==10 || val==32;
    	}
    	void readMin500()throws IOException{
    		while(lenBuf<500){
    			int l=in.read(buf,lenBuf,maxLenB-lenBuf);
    			if(l==-1)
    				throw new IOException();
    			lenBuf+=l;
    		}
    	}
    	void read()throws IOException{
    		if(posBuf>=maxLenB){
    			posBuf%=maxLenB;
    			lenBuf=0;
    		}
    		int l=in.read(buf,lenBuf,maxLenB-lenBuf);
    		if(l==-1)
    			throw new IOException();
    		lenBuf+=l;
    	}
    
    	private Olimp(final Pset answer)throws IOException{	
    		readMin500();
    		circles=new Circle[(int)readDouble()];
    		for(int sp=0;sp<circles.length;sp++){
    			readMin500();
    			circles[sp]=new Circle(readDouble(), readDouble());	
    
    			int readData=0;
    			int shift=0;
    			{
    				byte temp=buf[posBuf];
    				while(buf[posBuf+shift]==temp)
    					shift++;
    				shift%=10;
    				posBuf+=shift;
    				readData+=shift;
    			}
    			
    			int data=0;
    			for(int i=0;i<32;i++,posBuf+=10){
    				data<<=1;
    				data|=buf[posBuf]==48?(byte)0:(byte)1;
    			}
    			readData+=320;
    			
    			m1:while(posBuf<maxLenB){
    				for(;posBuf<lenBuf;posBuf+=10,readData+=10){
    					if(cash[data&0xFF]==data){
    						double len=            readData             -320 +maxLen10-cashLen[data&0xFF]*10   ;
    						circles[sp].r=len*kof;
    						break m1;
    					}
    							
    					data<<=1;
    					data|=buf[posBuf]==48?(byte)0:(byte)1;
    				}
    				read();
    			}
    			in.skip(maxLen10-(readData+(lenBuf-posBuf)));
    			posBuf=0;
    			lenBuf=0;
    		}
    		int testPset=1;
    		for(int i=2;i<circles.length;i++){
    			if(circles[testPset].r<circles[i].r){
    				testPset=i;
    			}
    		}
    		Pset p0=new Pset();
    		Pset p1=new Pset();
    		int gggg=intersection(circles[0],circles[testPset],p0,p1);
    		double delta0=precisionAll(p0,circles);
    		if(gggg==1){
    			answer.x=p0.x;
    			answer.y=p0.y;
    			return;
    		}
    		double delta1=precisionAll(p1,circles);
    		if(delta0<delta1){
    			answer.x=p0.x;
    			answer.y=p0.y;
    		}else{
    			answer.x=p1.x;
    			answer.y=p1.y;
    		}
    	}
    	static double pow2(double x){
    		return x*x;
    	}
    	static double precisionAll(Pset p0,Circle[] circles){
    		double delta=0;
    		Pset sum=new Pset();
    		Pset temp=new Pset();
    		for(int j=1;j<7;j++){
    			sum.x=0;
    			sum.y=0;
    			for(int i=0;i<circles.length;i++){
    				precision(p0,circles[i],temp);
    				sum.x+=temp.x;
    				sum.y+=temp.y;
    				delta=pow2(temp.x-p0.x)+pow2(temp.y-p0.y);
    			}
    			p0.x=sum.x/circles.length;
    			p0.y=sum.y/circles.length;
    		}
    		return 	delta;
    	}
    	static void precision(Pset pset,Circle circle,Pset returnPset){
    		double dx=pset.x-circle.x;
    		double dy=pset.y-circle.y;
    		double dz=circle.distanceTo(pset);
    		if(dz<0.0000001){
    			if(circle.r<0.000001){
    				returnPset.x=circle.x;
    				returnPset.y=circle.y;
    				return ;
    			}
    			
    			returnPset.x=pset.x+ circle.r;
    			returnPset.y=pset.y+circle.r;
    			return;	
    		}
    		returnPset.x=circle.x+dx*circle.r/dz;
    		returnPset.y=circle.y+dy*circle.r/dz;
    	}
    	static int intersection(Circle circle0,Circle circle1,Pset first,Pset second) 
    	{
    		double x0,y0;
    		double d;
    		double a;
    		double h;
    
    		d=circle0.distanceTo(circle1);
    		
    		double deltaX=circle1.x - circle0.x;
    		double deltaY=circle1.y - circle0.y;
    		
    		if(d >= circle0.r+circle1.r) {
    			first.x = circle0.x+deltaX*circle0.r/(circle0.r+circle1.r);
    			first.y = circle0.y+deltaY*circle0.r/(circle0.r+circle1.r);
    			return 1; 
    		}
    		if(d <= abs(circle0.r-circle1.r)) { 
    			deltaX/=d;
    			deltaY/=d;
    			if(circle1.r<circle0.r){
    				first.x = (circle0.x+deltaX*circle0.r   +  circle1.x+deltaX*circle1.r)/2;
    				first.y = (circle0.y+deltaY*circle0.r   +  circle1.y+deltaY*circle1.r)/2;
    			}else{
    				first.x = (circle0.x-deltaX*circle0.r   +  circle1.x-deltaX*circle1.r)/2;
    				first.y = (circle0.y-deltaY*circle0.r   +  circle1.y-deltaY*circle1.r)/2;
    			}
    				
    			return 1;
    		}
    
    		a= (pow2(circle0.r) - pow2(circle1.r) + d*d ) / (2*d);
    		h= sqrt( pow2(circle0.r) - pow2(a));
    
    		x0 = circle0.x + a*deltaX / d;
    		y0 = circle0.y + a*deltaY / d;
    
    		first.x= x0 + h*deltaY / d;
    		first.y= y0 - h*deltaX / d;
    		//if(a == circle0.r ) return 1;
    		second.x= x0 - h*deltaY / d;
    		second.y= y0 + h*deltaX / d;
    		return 2;
    	}
    }
    class Pset{
    	double x;
    	double y;
    	Pset(){
    	}
    	Pset(double xx,double yy){
    		x=xx;
    		y=yy;
    	}
    	double distanceTo(Pset p){
    		return sqrt((x-p.x)*(x-p.x)+(y-p.y)*(y-p.y));
    	}
    	void print(){
    		System.out.println(""+x+" "+y);
    	}
    	void printDlta(Pset answer){
    		System.out.println(""+(x-answer.x)+" "+(y-answer.y)+" "+Math.sqrt((x-answer.x)*(x-answer.x)+(y-answer.y)*(y-answer.y)));
    	}
    
    }
    class Circle extends Pset{
    	double r;
    	Circle(double xx,double yy){
    		super(xx,yy);
    	}
    	Circle(double xx,double yy,double rr){
    		super(xx,yy);
    		this.r=rr;
    	}
    }
    

С полной таблицей результатов можно ознакомится тут. Красным подсвечены результаты, выходящие за допустимые пределы (ошибка более 1000 метров, или время работы более 5 секунд. ). Скачать все решения, их ответы и результаты компиляции — можно тут. В верхней части таблицы все еще есть read-only пользователи, исправляем: ibessonov, where-is-s, Leng, Kofko, shuternay, wSpirit, dimka-74.
Читать дальше →
Total votes 33: ↑24 and ↓9 +15
Comments 50

Майское хабрасоревнование: делаем свой ГЛОНАСС

Reading time 5 min
Views 29K
Шла холодная зима 2063 года… Вы, сидя в избушке в сибирских степях, попивая горячий чай, из ностальгических побуждений достали свой любимый раритетный смартфон образца 2014 года с поддержкой ГЛОНАСС — однако он почему-то не нашел ни одного спутника. Вдруг тишину разрезал пронзительный звонок красного правительственного телефона — голос на той стороне затараторил: оказалось все спутники ГЛОНАСС вышли из строя из-за неизвестного сбоя… (ТЗЧ? Закладки? Кто теперь разберет....)

Что-ж, надежда теперь только на вас — нужно в кратчайшие сроки (к понедельнику) разработать новую систему спутниковой навигации с учетом достижений науки и техники 2063 года: в связи с тем, что термоядерные реакторы и аннигиляционные двигатели стали достаточно компактными, чтобы помещаться на борту спутника — их теперь фиксируют в одной точке в околоземном пространстве, никакой орбиты больше нет. Соответственно, альманах и эфемериды (параметры орбиты спутников) больше не нужно передавать со спутника на землю.
Читать дальше →
Total votes 44: ↑33 and ↓11 +22
Comments 176

U.S. Robotics Pilot 5000 — первый успешный КПК. Внутренности, модем, использование с современными ОС

Reading time 2 min
Views 37K
Давным-давно, в 1996 году палмы назывались пилотами, и выпускала их компания U.S. Robotics (как и модемы). Мне удалось достать их самый ранний КПК — U.S. Robotics Pilot 5000 — с прокачанной до 1Мб памятью: да-да, в то время карманные компьютеры поддерживали апгрейд (привет Google Project Ara) — можно было получить ИК порт и больше памяти, или например модуль приема пейджинговых сообщений).

Процессор — Motorola Dragonball, работающий на частоте 16Мгц. Впрочем, этого было более чем достаточно для любых применений: в PalmOS 1.0 правильно написанные приложения были «всегда запущены» — и переключение между ними было практически мгновенным. Монохромный экран с разрешением 160x160 пикселей и без подсветки — жрал минимум энергии.

Читать дальше →
Total votes 97: ↑95 and ↓2 +93
Comments 35

Анонс майского хабрасоревнования по программированию на Java от WayRay

Reading time 1 min
Views 12K
Не знаете чем заняться в майские праздники? Решение есть!

Мы в WayRay сейчас как раз ищем разработчиков и у меня возникла идея: а что, если совместить приятное с полезным, и за деньги, которые обычно отдают рекрутерам — попробовать организовать маленькое соревнование с призами, а с десяток авторов лучших результатов — помимо вручения призов пригласить на собеседование? (вы естественно можете забрать приз и не идти на собеседование — это сугубо добровольно).

Что-ж, посмотрим, что из этого выйдет!

Сроки проведения соревнования: с 9 мая 0:00 по 11 мая 23:59 по московскому времени.
Условия будут опубликованы 9 мая в 0:00 — в этих же хабах на хабре, прием решений соответственно не позднее 11 мая 23:59.
Читать дальше →
Total votes 41: ↑36 and ↓5 +31
Comments 13

Пятьдесят оттенков инфракрасного

Reading time 4 min
Views 130K
Не знаю как вам, а мне всегда было интересно: как выглядел бы мир, если бы цветовые каналы RGB в глазу человека были чувствительны к другому диапазону длин волн? Порывшись по сусекам, я обнаружил инфракрасные фонарики (850 и 940нм), комплект ИК фильтров (680-1050нм), черно-белую цифровую камеру (без фильтров вообще), 3 объектива (4мм, 6мм и 50мм) расчитанные на фотография в ИК свете. Что-ж, попробуем посмотреть.

На тему ИК фотографии с удалением ИК фильтра на хабре уже писали — на этот раз у нас будет больше возможностей. Также фотографии с другими длинами волн в каналах RGB (чаще всего с захватом ИК области) — можно увидеть в постах с Марса и о космосе в целом.

Читать дальше →
Total votes 168: ↑166 and ↓2 +164
Comments 43

Внутренности карты Яндекс.Денег — MasterCard PayPass

Reading time 1 min
Views 129K
Недавно в банках начали выдавать карты Visa/MasterCard с оплатой в «одно касание» — PayPass, по радио. Мне было интересно посмотреть, как это работает — так что я безжалостно «разобрал» карту MasterCard Яндекс.Денег. Результаты вскрытия — под катом.

Также будет интересно оценить сложность и технологию производства «карточного» чипа, в свете нынешних разговоров о «национальных платежных системах».

Читать дальше →
Total votes 216: ↑203 and ↓13 +190
Comments 125

Самый маленький Хабра-кармограф — для munin

Reading time 1 min
Views 5.2K
Несколько раз уже на Хабре писали карматрекеры — отображающие изменение кармы на графике. Самый известный и живой до сих пор — Хаброметр. Однако для моих целей он не вполне подходил — слишком редкий опрос, раз в сутки (впрочем, в соответствии со старыми правилами использования API хабра — массовый опрос с бОльшей частотой затруднителен).

Так что я написал свой крошечный munin-плагин для хабра. Если вам он не нужен, то ничего интересного вы под катом не увидите: несколько строчек PHP, парсинг XML стандартными средствами — на все про все 10 минут. Частота опроса — стандартная, раз в 5 минут.
Читать дальше →
Total votes 21: ↑16 and ↓5 +11
Comments 7

Поддельные аудиофильские операционные усилители — OPA627

Reading time 2 min
Views 120K
Покупая всякую всячину на ebay, я совершенно случайно наткнулся на OPA627. Это довольно старый, популярный и качественный операционный усилитель, который иногда используют в усилителях аудиофилы (и не только). Однако меня смутила цена — у производителя (Texas Instruments / Burr Brown) они по 16-80$ (в зависимости от исполнения), а на ebay их продавали по 2.7$, включая доставку.

Сразу ясно, что там что-то не то, но интересно было узнать, что именно. Заказал 1шт, а для сравнения — OPA627 в металлическом корпусе за 5$, явно откуда-то выпаянную. Результаты сравнения внутренностей — под катом.
Читать дальше →
Total votes 154: ↑148 and ↓6 +142
Comments 63

Почему в России почти нет гражданского/коммерческого высокотехнологичного производства?

Reading time 27 min
Views 407K
Статью с обзором ситуации с микроэлектроникой в России я закончил утверждением, что сейчас в России есть технические возможности для создания любых военных микросхем (если не считаться с ценой). Однако и в комментариях к той статье, и во многих других — всех больше волновал вопрос отсутствия (на уровне погрешности измерений) производства чисто-коммерческих (гражданских) высокотехнологичных продуктов. Этот вопрос волновал и меня, потому я постоянно мучил вопросами всех, кто так или иначе связан с высокими технологиями и бизнесом в России.

Ответ на него важен, если вы сами хотите создать конкурентный высокотехнологичный продукт — чтобы не потратить лучшие годы жизни в изначально неравных условиях.

Под катом попробуем разобраться чем отличаются «высокотехнологичные» компании от «низкотехнологичных», что нужно, чтобы высокотехнологичные компании могли рождаться и выживать, почему с софтом у нас лучше, чем с хардом, с чего начиналась кремниевая долина в США и можно ли её «скопировать», почему Китай всех рвет, а также — окинем взором все, что происходит в Сколково, Роснано, фонде перспективных исследований и приведут ли они к расцвету российских инноваций. Безусловно, я где-то могу ошибаться — буду рад дополнениям в комментариях.

Сразу нужно отметить, что в связи с многогранностью проблемы объем статьи получился довольно большой, так что можно начать читать с резюме в конце, и затем прочитать лишь те разделы, которые вызовут интерес. Сразу хочу предупредить — повествование «нелинейное», соседние заголовки могут описывать разные аспекты проблемы и быть друг с другом практически не связанными.
Читать дальше →
Total votes 389: ↑380 and ↓9 +371
Comments 304

Information

Rating
1,355-th
Location
Zürich, Швейцария
Registered
Activity