<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.3">Jekyll</generator><link href="https://lispc.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://lispc.github.io/" rel="alternate" type="text/html" /><updated>2026-07-01T07:44:44+00:00</updated><id>https://lispc.github.io/feed.xml</id><title type="html">Zhuo Zhang</title><subtitle>Personal blog of Zhuo Zhang — writing about programming, Haskell, cryptography, zero-knowledge proofs and building things.</subtitle><author><name>Zhuo Zhang</name><email>mycinbrin@gmail.com</email></author><entry><title type="html">Fluidex 近况更新</title><link href="https://lispc.github.io/2021/03/03/fluidex" rel="alternate" type="text/html" title="Fluidex 近况更新" /><published>2021-03-03T00:00:00+00:00</published><updated>2021-03-03T00:00:00+00:00</updated><id>https://lispc.github.io/2021/03/03/fluidex-</id><content type="html" xml:base="https://lispc.github.io/2021/03/03/fluidex"><![CDATA[<ul id="markdown-toc">
  <li><a href="#技术进展" id="markdown-toc-技术进展">技术进展</a></li>
  <li><a href="#社群状态" id="markdown-toc-社群状态">社群状态</a></li>
  <li><a href="#融资状态" id="markdown-toc-融资状态">融资状态</a></li>
  <li><a href="#对其他项目的技术贡献" id="markdown-toc-对其他项目的技术贡献">对其他项目的技术贡献</a></li>
  <li><a href="#其他" id="markdown-toc-其他">其他</a></li>
</ul>

<p>关于我们：Fluidex 团队正在开发 Ethereum 上第一个无许可上币的订单簿 DEX。项目的完整介绍可以看这篇文章：<a href="http://lispc.github.io/2020/11/28/fluidex">http://lispc.github.io/2020/11/28/fluidex</a>。</p>

<p>下面介绍从 2021 年初项目启动以来，团队在各方面的一些工作。</p>

<h1 id="技术进展">技术进展</h1>

<h3 class="no_toc" id="plonkit">Plonkit</h3>

<p>工欲善其事，必先利其器。</p>

<p>Plonkit 是一个 Fluidex 团队开发的 PLONK 零知识证明工具包。通过使用 Plonkit，用户可以使用更容易上手的 DSL 来实现自己的零知识证明电路代码，而不需要学习 Rust 语言和底层密码学库的复杂细节。</p>

<p>Plonkit 底层基于 bellman_ce 密码学库开发。目前的功能有，本地 setup（仅限开发使用，正式的 setup 需要 MPC），电路证明和本地验证，solidity 验证合约生成等。</p>

<p>Plonkit 开源以来收到了很多开发者的关注，现在是团队在 github 上获得标星最多的项目。</p>

<p>我们正在实现 server 模式，以便 plonkit 能够被作为长期运行的证明服务启动。未来我们会进一步实现集群证明服务功能。更长远地，我们可能会加入 custom gates 来进一步提升系统的性能上限，此外我们还会专门为 PLONK 及其变种持续改进 DSL。</p>

<p>更多请访问 github: <a href="https://github.com/Fluidex/plonkit">https://github.com/Fluidex/plonkit</a></p>

<h3 class="no_toc" id="交易所">交易所</h3>

<p>Fluidex 团队在过去几个月中，完成了交易所撮合引擎后端和网页端的第一个版本。后端撮合引擎部分已经开源，使用 Rust 语言实现了纯内存撮合，能够达到数千 TPS 的性能，这将保证我们交易系统在可见未来系统的流畅性和稳定性。项目已经在 github 开源。我们仍在持续完善中。（没有经过真实业务的锤炼，目前建议仅作学习交流使用）。</p>

<p>目前交易所后端已经开源，前端暂未开源。
更多请访问 github: <a href="https://github.com/Fluidex/dingir-exchange">https://github.com/Fluidex/dingir-exchange</a></p>

<h3 class="no_toc" id="零知识证明电路和智能合约">零知识证明电路和智能合约</h3>

<p>我们完成了<a href="https://github.com/Fluidex/rescue-hash-js">第一个 Javascript Rescue Hash 的实现</a>，也开发了<a href="https://github.com/Fluidex/circuits/blob/master/src/lib/rescue.circom">第一个 circom 语言版本的 Rescue Hash 电路代码</a>。基于 Echarts 旭日图，我们开发了<a href="https://github.com/Fluidex/circuits/blob/master/tools/benchmark/profile_circuit.js">可视化 profile 电路的工具</a>，用户可以快速分析出自己电路代码中 cost 最大的是哪部分，便于进一步做细致的优化。</p>

<p>我们完成了最基础的充提&amp;转账&amp;交易的电路代码，尚有较多功能和性能细节需要进一步完善，暂不展开介绍。当然，所有代码都在很早期，没有任何审计，不建议生产使用。</p>

<p>上述所有成果都已经开源在我们的代码库中。更多请访问 github: <a href="https://github.com/Fluidex/circuits">https://github.com/Fluidex/circuits</a></p>

<h3 class="no_toc" id="awesome-plonk">Awesome Plonk</h3>

<p>这是我们收集的 PLONK 相关的优质资料的汇编。涵盖论文，实现，Demo，论坛，博客文章， 博客/视频等多方面的学习资料。</p>

<p>更多请访问 github: <a href="https://github.com/Fluidex/awesome-plonk">https://github.com/Fluidex/awesome-plonk</a></p>

<h1 id="社群状态">社群状态</h1>

<p>目前我们仅在 Telegram 上维护了英文技术社群。两个月来已经有 100 多位对我们感兴趣的开发者加入。未来我们会在那里持续更新我们的技术进展。</p>

<h1 id="融资状态">融资状态</h1>

<p>过去几个月，Fluidex 从几位私人投资者中已经完成共计超过 50 万美元的融资。在此感谢这些业界前辈在财务和其他方面给予我们的支持。</p>

<p>这些钱够我们目前的开发使用。我们暂时不寻求进一步的融资。</p>

<h1 id="对其他项目的技术贡献">对其他项目的技术贡献</h1>

<p>我们发现了 matters lab 开源的 PLONK solidity 验证合约代码中 <a href="https://github.com/matter-labs/zksync/pull/284">当输入个数大于 1 时的 bug</a>，并且提交了上游 pull request。（zksync 线上系统不触发这条代码路径，正确性和安全性不受这个 bug 影响。）</p>

<p>Fluidex 正在参与 Hermez 项目的 phase 2 trusted setup ceremony，希望通过自己的力量，为更广泛的 Layer2 社区做出贡献。（解释：“phase 2 trusted setup ceremony”是什么？ 使用 Groth16 协议的 zk-rollup 的项目在上线前，一般会通过多方计算保证一些密码学参数的安全，“phase 2 trusted setup ceremony” 就是这样一个多方计算的过程。只要所有参与的用户有一个是不作恶的，整体的密码学系统就是安全的。）</p>

<h1 id="其他">其他</h1>

<p>在国贸租了个小办公室～ 可以开心刷夜干活啦～ <br />
欢迎对我们项目有兴趣的朋友加入团队～ <a href="https://github.com/Fluidex/we_are_hiring">https://github.com/Fluidex/we_are_hiring</a></p>]]></content><author><name>Zhuo Zhang</name><email>mycinbrin@gmail.com</email></author></entry><entry><title type="html">Fluidex: A zkrollup layer2 DEX</title><link href="https://lispc.github.io/2020/11/30/fluidex-a-zkrollup-layer2-dex" rel="alternate" type="text/html" title="Fluidex: A zkrollup layer2 DEX" /><published>2020-11-30T00:00:00+00:00</published><updated>2020-11-30T00:00:00+00:00</updated><id>https://lispc.github.io/2020/11/30/fluidex-a-zkrollup-layer2-dex</id><content type="html" xml:base="https://lispc.github.io/2020/11/30/fluidex-a-zkrollup-layer2-dex"><![CDATA[<h1 id="what-is-fluidex">What is FluiDex</h1>
<p>For those familiar with cutting-edge technology, FluiDex is a Layer 2 decentralized exchange on Ethereum. We will use PLONK-based zkrollup technology to achieve high-performance transactions, while being able to reduce the cost of each transaction to less than 0.0001 USD. We will be the first order book exchange on Ethereum to use PLONK based validity proof.</p>

<p>For the general public, FluiDex is a crypto asset exchange similar to Coinbase or Huobi. The advantage is that your assets are absolutely safe. You don’t need to trust the team of the exchange to be ethical or law-abiding. You only need to trust cryptography and code. The disadvantage is that it will be more difficult to use, for example, transaction fees will be higher in some cases.</p>

<h1 id="why-build-fluidex">Why build FluiDex</h1>
<p>“Build a safe, professional and easy-to-use digital asset trading platform” is our long-term vision.</p>

<p>In the scope of technology products that exist today, “security” means Ethereum, which requires almost no explanation. I will talk about how FluiDex understands “professional trading” in the below paragraph.</p>

<p>We roughly divide the traders in the market into two categories. One category is called “speculative retail investors”. The feature is that they don’t care about miners’ fees and handling fees, and don’t care about the slippage loss of market orders. They just want to be able to easily buy certain assets. Because they bet that this asset will increase several times, the other type, we call it “professional traders”, they care about miners’ fees and handling fees, they are skilled in using derivative hedging, they can arbitrage through different exchanges, and they are skilled in using limit/market/stoploss/FOK/IOC/AON order as a tool for different purposes, may use a program to do automatic trading.</p>

<p>On today’s Ethereum, exchanges such as Uniswap based on algorithm-based automated market making have gained high popularity. Except higher miner fees, such exchanges generally meet the needs of “speculative retail investors”. However, for this type of exchange, liquidity takers can only list market price orders. For liquidity maker, there will be profit due to rebates when the price is stable, and losses when the price fluctuates sharply. The above shortcomings can be tolerated for “speculative retail investors”, but they are unimaginable for “professional traders”. For every trader with a traditional financial background, if you tell them “there is no order book, you can’t place an order for rebates; you can only place a market order, and set a slippage threshold at most”, they will be shocked.</p>

<p>We expect that more and more real assets will circulate in a decentralized manner in the future, and more and more types of traders will participate in trading. Too simple swap exchanges will not be able to meet the needs of quite a few advanced traders. The traditional order book exchange will be a much easier solution.</p>

<p>So why hasn’t the order book decentralized exchange exploded in the past few years? On the one hand, it is the ecological environment. In the early years, there were not many assets carried on Ethereum. The USDT stablecoin, which is well-known to traders, did not circulate on Ethereum two years ago. On the other hand, technology. The early and simple implementation of order book exchanges will make the cost of miners’ fees for each commission and transaction comparable to swap exchanges. Expensive order and transaction costs constrain the explosion of order book exchanges. Today Thanks to the springing up of zero-knowledge proof technology in the past two years, we are finally able to provide a trading experience with zero-cost listing orders and 0.0001$-cost transaction.</p>

<p>In summary, the development of a decentralized economy has brought more and more traders and trading needs, and order book exchanges can better meet the needs of professional traders. In the past few years, the development of cryptography technology has made it possible for high-performance, low-cost and secure order book transactions. Therefore, it is time to build FluiDex now.</p>

<h1 id="similar-products-and-projects">Similar products and projects</h1>

<ol>
  <li>Traditional centralized exchange. For quite a few, even more than half of the people, this type of exchange is good enough to use. However, for some people who have high requirements for fund security &amp; anonymity, the hidden danger of black swan always exists in centralized exchanges. Even for a big exchange like OKEx, it happened not long ago that the exchange was unable to withdraw the coin because the founder lost contact for more than a month.</li>
  <li>Algorithmic automated market making exchange. Typical is Uniswap, which sets the price of buying and selling assets by always ensuring that the number of asset A * the number of asset B == the fixed value. In the previous paragraph, we believe that such exchanges are not enough for professional traders. But it must be acknowledged that the composability of such swap exchanges is an advantage that Layer2 DEX does not have, and Layer2 DEX is more difficult to become part of the “Defi building block”.</li>
  <li>Order book exchange based on optimistic rollup technology. This type of exchange has high performance and is easy to develop, but it has two major disadvantages. The first is that withdrawing from such exchanges requires confirmation time of weeks, which is completely unacceptable for many traders. Second, the security of optimistic rollup is not as good as “as safe as L1” zk rollup.</li>
  <li>Other products with similar technical decisions, such as diversifi and loopring. Yes, in a nutshell, FluiDex will compete head-to-head with them. That there are already one or two players in a potential big market, is not a reason why new players should not enter. It is not true that since OKEx is running well, Binance should not start a business. In addition, FluiDex and these projects will have some different decisions both in technology and product. For example, from a technical perspective, we will use PLONK as the protocol of zero-knowledge proof, which will bring faster product iteration, from a product perspective, we are likely to implement permissionless token listing.</li>
</ol>

<h1 id="decentralized-governance--token">Decentralized Governance &amp; Token</h1>

<p>I believe that our exchange is a traditional “centralized” exchange, the only difference is the self-custody of assets. There are many interpretations of “decentralization”, the decentralization of assets, the decentralization of control (“governance”), and even the decentralization of teams. Based on our vision, the decentralization of assets (ie, the self-custody of assets) is necessary for us. But, at least today, we believe that decentralization of governance is neither necessary nor sufficient for building a great product. Any team that does a product will investigate users and markets, but no team will decide the future of product only through user votes. Customers and shareholders are two kinds of people. You should not force or expect customers to become shareholders. For the FluiDex team, the customer is supreme, but there will be no so-called “decentralized” governance in the future. The decision-making power of the future of the product will always be in the hands of the management team, and users are expected to vote for our success or failure with their feet.</p>

<p>Based on our understanding of governance philosophy above, FluiDex will not issue “governance tokens” in the foreseeable future, but we are not opposed to issuing tokens with dividend rights for fundraising. For example, it is entirely possible for us to issue a token and guarantee to buy back this token with 10% of the monthly gross profit for the next 3 years.</p>

<h1 id="project-status--schedule--financing">Project status &amp; schedule &amp; financing</h1>

<p>We have completed a relatively small seed round of financing. According to estimates, we should be able to support us to make a minimal demo. It is estimated that it will take 4-5 months to make this minimum demo, and then we will make a second round of much larger financing to support us in making a complete product. In the next six months, I may continue to contact investors, but in principle, I may not seek further investment unless the valuation and terms are close to the second round price of my expectation.</p>

<h1 id="contract--recruitment">Contract &amp; Recruitment</h1>

<p>FluiDex Labs is committed to building the next generation of professional decentralized exchanges. We will use PLONK zero-knowledge proof technology on Ethereum to develop a high-performance order book digital asset spot exchange. The core team members are from  several well-known blockchain and exchange teams. Among our investors, there are experienced entrepreneurs who have worked in the cryptocurrency industry for many years, as well as the founders of the traditional high-frequency trading funds. Any friends who are interested in our products, or want to join us or invest in us, are welcome to contact us for further communication. You can join our telegram group: <a href="https://t.me/fluid_dex">https://t.me/fluid_dex</a></p>]]></content><author><name>Zhuo Zhang</name><email>mycinbrin@gmail.com</email></author><summary type="html"><![CDATA[What is FluiDex For those familiar with cutting-edge technology, FluiDex is a Layer 2 decentralized exchange on Ethereum. We will use PLONK-based zkrollup technology to achieve high-performance transactions, while being able to reduce the cost of each transaction to less than 0.0001 USD. We will be the first order book exchange on Ethereum to use PLONK based validity proof.]]></summary></entry><entry><title type="html">介绍下我的创业项目 FluiDex: Yet Another Layer2 DEX</title><link href="https://lispc.github.io/2020/11/28/fluidex" rel="alternate" type="text/html" title="介绍下我的创业项目 FluiDex: Yet Another Layer2 DEX" /><published>2020-11-28T00:00:00+00:00</published><updated>2020-11-28T00:00:00+00:00</updated><id>https://lispc.github.io/2020/11/28/fluidex-</id><content type="html" xml:base="https://lispc.github.io/2020/11/28/fluidex"><![CDATA[<ul id="markdown-toc">
  <li><a href="#fluidex-是什么" id="markdown-toc-fluidex-是什么">FluiDex 是什么</a></li>
  <li><a href="#为什么要做-fluidex" id="markdown-toc-为什么要做-fluidex">为什么要做 FluiDex</a></li>
  <li><a href="#怎么看待类似的产品和项目" id="markdown-toc-怎么看待类似的产品和项目">怎么看待类似的产品和项目</a></li>
  <li><a href="#控制权--去中心化治理--发币" id="markdown-toc-控制权--去中心化治理--发币">控制权 &amp; 去中心化治理 &amp; 发币</a></li>
  <li><a href="#项目状态--时间表--融资" id="markdown-toc-项目状态--时间表--融资">项目状态 &amp; 时间表 &amp; 融资</a></li>
  <li><a href="#创始人--团队" id="markdown-toc-创始人--团队">创始人 &amp; 团队</a></li>
  <li><a href="#合作--交流--招聘" id="markdown-toc-合作--交流--招聘">合作 &amp; 交流 &amp; 招聘</a></li>
</ul>

<h1 id="fluidex-是什么">FluiDex 是什么</h1>
<p>对于熟悉前沿技术的人来说，FluiDex 是一个在以太坊上的 Layer2 去中心化交易所。我们将使用基于 PLONK 的 zkrollup 技术来实现高性能交易，同时能够将每笔交易的成本压缩到传统去中心化交易所的 1/100 以下。我们将会是以太坊上第一个使用 PLONK 的基于 validity proof 的订单簿交易所。</p>

<p>对于普通大众来说，FluiDex 是一个类似 Coinbase 或者 火币 的加密资产交易所，优点是你的资产绝对安全，你不需要信任交易所创始人有道德或守法律，你只需要信任密码学和代码。缺点是会更不好用一些，例如交易费用在一些情况下会更高。</p>

<h1 id="为什么要做-fluidex">为什么要做 FluiDex</h1>
<p>“做一个安全专业好用的数字资产交易平台” 是我们长期的愿景。</p>

<p>在今天存在的技术产品范围内看，“安全”就意味着以太坊，这个几乎不用解释。下面我会讲讲 FluiDex 怎么理解“专业的交易”。</p>

<p>我们把市场中的交易者粗略分为两类，一类我们叫“投机散户”，特点是不在乎矿工费和手续费，不在乎市价单的滑点损失，只是希望能够方便地买入某种资产，因为他们赌这种资产会涨几倍，另一类，我们称“专业交易员”，他们在乎矿工费和手续费，熟练使用衍生品套保，能够通过不同交易所价差套利，熟练使用限价/止损/市价/FOK/IOC/AON单作为自己不同目的的工具，可能会使用程序做自动交易。</p>

<p>在今天的以太坊上，Uniswap 这类基于算法自动化做市的交易所获得了很高的热度。这类交易所除了矿工费较高外，大体上满足了“投机散户”的需求。但是，这类交易所，对 liquidity taker 来说，只能挂市价单，对 liquidity maker 来说，价格稳定时有返佣盈利，价格剧烈波动时有损失。以上这些缺点，对于 “投机散户” 是可以容忍的，但是对于“专业交易员”是无法想象的。对于每一个传统金融出身的交易者，你如果告诉他们“这里没有订单簿，你也不能挂单吃返佣；你们只能下市价单，最多设置一下滑点”，他们都会惊掉下巴。</p>

<p>我们预期未来会有越来越多的真实资产会以去中心化的方式流通，也会有越来越多类型的交易者参与交易。过于简单的 swap 类交易所，将无法满足相当多的高级交易者的需求。传统的订单簿交易所，将是一个好用得多的解决方案。</p>

<p>那过去几年为什么订单簿去中心化交易所没有爆发呢？一方面是生态环境，早几年以太坊上承载的资产还不算特别多，要知道炒币者皆知的 USDT 稳定币，两年前都没有在以太坊上流通。另一方面是技术，订单簿交易所的早期简单实现，会使得每笔委托和交易的矿工费成本和 swap 类交易所相当，昂贵的挂单和交易成本束缚了订单簿交易所的爆发，而今天，得益于过去两年零知识证明技术雨后春笋般地爆发，我们终于能提供 0 成本挂单，0.0001 成本成交的交易体验。</p>

<p>综上，去中心化经济的发展，带来越来越多的交易者和交易需求，订单簿交易所才能较好地满足专业交易者的需求。而过去几年密码学技术的进展，使得高性能低成本安全的订单簿交易所成为可能。因此，现在做 FluiDex，恰逢其时。</p>

<h1 id="怎么看待类似的产品和项目">怎么看待类似的产品和项目</h1>

<ol>
  <li>传统中心化交易所。对于相当多，甚至是一大半的人来说，这类交易所已经足够好用了。不过对于一些对资金安全 &amp; 匿名性要求较高的人来说，中心化交易所始终存在黑天鹅的隐患，是不够的。即使是 OKEx 这样的大交易所，不久前也发生了因为创始人失联一个多月没法提币的事情。</li>
  <li>算法自动化做市交易所。典型的是 Uniswap，通过始终保证资金池中 资产A的数量 * 资产B的数量 == 定值，来确认买卖资产的价格。上一段中，我们认为这类交易所对于专业交易者是不够用的。但不得不说，这类交易所的 composability 是 Layer2 DEX 没有的优势，Layer2 DEX 更难成为 “Defi 积木” 的一部分。</li>
  <li>基于 optimistic rollup 技术的订单簿交易所。这类交易所性能较高，而且开发容易，但是有两个重大缺点。第一是，资金从这种交易所提出，需要周尺度的确认时间，这对很多资金是完全没法接受的。第二，optimistic rollup 的安全性是有假设有牺牲的，和 zk rollup 的“绝对安全“不同。</li>
  <li>其他类似技术路线的产品，如 diversifi 和 loopring。是的，概括地说，FluiDex 将和他们硬碰硬头对头地竞争。因为我们觉得，一个潜在的大赛道已经有了一两个玩家，不是后面玩家不该进入的理由。不能说 OKEx 运行很好，Binance 就不该创业了。此外，FluiDex 和这些项目还会有一些具体的技术和产品路线区分，例如技术角度，我们会使用 PLONK 作为零知识证明的底层，这会带来更快的产品迭代效率，产品角度，我们很可能会实现无许可上币。</li>
</ol>

<h1 id="控制权--去中心化治理--发币">控制权 &amp; 去中心化治理 &amp; 发币</h1>
<p>我内心更倾向认为，我们的交易所就是一个传统的“中心化”交易所，唯一的不同是资产的自托管。“去中心化”有很多种解读，资产的去中心化，控制权（“治理”）的去中心化，甚至团队的去中心化。基于我们的愿景来看，资产的去中心化（即资产的自托管），对我们是必需的。但是，至少今天，我们认为控制权的去中心化对于构建一个伟大产品而言，既非必要，也不充分。任何团队做产品都会调研，但是不会有团队仅仅通过用户的投票来决定未来。从古至今，客户和股东就是两种人，你不应该强迫或者期待客户成为股东。对于 FluiDex 团队来说，客户至上，但可见未来不会有所谓“去中心化”治理，产品的未来的决策权始终会在团队管理层手中，期待用户用脚来给我们的成败投票。</p>

<p>基于以上我们对控制权的认知，FluiDex 在可见未来不会发行有投票权的 “治理代币”，但是我们不反对发行有分红权的代币来做募资。比如，我们完全有可能发行一种代币，保证用今后3年每月毛利的10%来回购这种代币。</p>

<h1 id="项目状态--时间表--融资">项目状态 &amp; 时间表 &amp; 融资</h1>
<p>我们目前账上有一些资金，预计可以支撑我们团队在2021年4-5月左右，做一个最小 Demo 出来。之后我们会做进一步融资，以支持我们能够做一个完整的产品。未来几个月团队的主要精力会在开发产品本身上。</p>

<p><del>Update 2020.01.13<br />
近期有不少朋友在问进一步的融资预期。我下一步比较舒服的融资是放出 10% 的股份，换不低于 30 万美元的融资。
</del></p>

<p>Update 2020.02.24 
暂时不融资</p>

<h1 id="创始人--团队">创始人 &amp; 团队</h1>

<p><a href="#team">创始团队</a>:</p>

<p>CEO: 张卓。毕业于清华大学计算机系，曾任人工智能独角兽依图科技的语音识别负责人，曾负责 IOST 公链的研发。</p>

<p>CTO: 林浩宇。VRF-mining, RandChain, fair-atomic-swap 共同发明人。ZenGo 研究员。曾负责比原链研发。</p>

<h1 id="合作--交流--招聘">合作 &amp; 交流 &amp; 招聘</h1>

<p>FluiDex Labs 致力于构建下一代专业的去中心化交易所。我们将在以太坊上使用 PLONK 零知识证明技术，开发高性能的订单簿数字资产现货交易所。在我们的投资者中，有在加密货币圈耕耘多年的资深企业家，也有传统高频交易市场的创始人。任何对我们感兴趣的朋友，无论是关心我们产品，希望加入我们或者投资我们，都欢迎联系我们进一步沟通。可以加入我们的 telegram 群：<a href="https://t.me/fluid_dex">https://t.me/fluid_dex</a> (目前英文技术话题为主) ，或者直接添加我的 Telegram: <a href="https://t.me/lispczz">https://t.me/lispczz</a> 或 微信：lispcz。</p>

<p>我们正在招聘全职/兼职/实习工程师。完整的招聘信息在 <a href="https://github.com/Fluidex/we_are_hiring">we are hiring</a>。我们的开源项目在 <a href="https://github.com/Fluidex">Fluidex</a> 下面，目前有 <a href="https://github.com/Fluidex/plonkit">零知识证明工具包 Plonkit</a>，<a href="https://github.com/Fluidex/dingir-exchange">交易所撮合引擎 dingir-exchange</a>，<a href="https://github.com/Fluidex/circuits">零知识证明电路 DSL 代码</a>。对我们有兴趣的同学可以看一眼，可以对团队的日常工作有个感觉。我们团队 Base 在北京，希望新成员尽量在北京，如果你特别希望 remote 工作，我们可以看情况具体聊。</p>

<p>欢迎关注我们的 <a href="https://fluid-dex.medium.com/announcing-fluidex-building-the-first-plonk-layer2-dex-on-ethereum-e19136304a5d">Medium</a> 和 <a href="https://twitter.com/fluid_dex">Twitter</a>, 那里的文风比起我个人的 Blog 会更 “official” 一点。</p>]]></content><author><name>Zhuo Zhang</name><email>mycinbrin@gmail.com</email></author></entry><entry><title type="html">《新冠肺炎地级市疫情图》中的产品细节</title><link href="https://lispc.github.io/2020/01/29/pneumonia" rel="alternate" type="text/html" title="《新冠肺炎地级市疫情图》中的产品细节" /><published>2020-01-29T00:00:00+00:00</published><updated>2020-01-29T00:00:00+00:00</updated><id>https://lispc.github.io/2020/01/29/pneumonia</id><content type="html" xml:base="https://lispc.github.io/2020/01/29/pneumonia"><![CDATA[<p>前几天肺炎在全国迅速传播，我会时不时看一下周边城市是不是已经被病毒入侵了。这时我想，如果能做一个地级市的疫情地图，看起来会比读表格方便很多。于是我使用权威媒体的数据绘制了疫情图。最终的网页效果在 <a href="https://lispczz.github.io/pneumonia/">这里</a> 。下面记录了一些在此过程中我觉得有意思的细节。</p>

<h2 id="内嵌权威媒体">内嵌权威媒体</h2>
<p>我希望产品能“全面/准确/方便”地给用户信息。我自己画的地级市地图能够在“方便”这个维度给用户更多价值。考虑到前两个维度，我不该重新造一遍轮子，来把现有的数据重新可视化，而应当在网页内嵌一个权威媒体，如腾讯的疫情新闻页。这样用户来了之后，他得到的信息是腾讯新闻的超集。相反，如果我的网页只提供一个地级市疫情地图，那这个东西可以说是没那么有用的，应该只有非常少的用户愿意为了这个可有可无的功能，来收藏和访问这个网页。</p>

<h2 id="显示最后更新时间">显示“最后更新时间”</h2>

<p><a href="https://github.com/lispczz/pneumonia/issues/5">有人问</a> 为什么要五分钟更新一次，似乎没有必有，完全可以数据变动再更新。正如那里我回答的，不断变化的“最后更新时间”，是一种“反触发系统“，它用来表示系统状态是正常的。这个“最后更新时间”既是给我自己看的，也是给网页的用户看的。对我自己而言，我自己的开发资源有限，没办法做一个完善可靠的监控系统，让它在系统异常时候通知我，相比之下，让程序每五分钟告诉我系统是正常的，简单得多，也可靠得多。对用户而言，“最后更新时间”也会给他们信号：系统正常运行，数据可靠可信。</p>

<h2 id="展示">展示</h2>

<h4 id="病例数展示">病例数展示</h4>
<p>在点击地图的时候，会显示位置所在省份的每个城市的病例数据，另外点击位置所在的城市的结果一定会显示出来，不会被挤掉。例如点击无锡，“无锡市：3”一定会显示出来，一定不会被旁边很接近的“苏州市：5”覆盖掉。另外，我开始想过是不是要直接显示全国每个城市的结果，但后来觉得过于密密麻麻，最终放弃了这个选项。现在只有用户第一次点击之后，才开始显示相关省份的结果。</p>
<h4 id="桌面浏览器">桌面浏览器</h4>
<p>在桌面浏览器版本中，地图的大小是特意调过的。保证了桌面浏览器的用户，能看到网页下方有个“腾讯新闻”的上边沿，这暗示他们可以往下看，看看下面的权威媒体数据，这样不容易被用户忽视掉。</p>

<h2 id="特例处理">特例处理</h2>
<p>真实世界的数据不总是干净而统一的，常常需要特判“脏数据”。这里特殊处理有两处，一处是直辖市的行政级别和普通省份不一致，二是地名如何统一对应到国家标准地名。</p>

<h4 id="直辖市数据处理">直辖市数据处理</h4>
<p>直辖市处理需要额外的工作量。现在代码中，京津沪没有细分区县，只有重庆细分了区县，原因是重庆面积比较大，疫情比较严重，而且恰好 <a href="https://github.com/JackyRen">JackyRen</a> 帮写了重庆分区县绘图的代码。在后来新增的地图显示病例数功能中，我近一步对重庆城区和重庆郊县区别对待，前者作为一个整体统计显示，后者分开处理。因为重庆城区比较集中，统计上和显示上，分开似乎都没有必要。好比单独统计崇文区宣武区闸北区，有什么意义？</p>

<h4 id="地名标准化">地名标准化</h4>

<p>地名处理中，输入是新闻媒体中编辑手动写的地名，输出是国家标准地名。共有三种优先级从高到低的方法来顺次处理，前面的优先级高的方法没法处理时，才会使用后面的优先级低的方法尝试。</p>

<ul>
  <li>第一步是我自己手工维护的特判规则，如“满洲里”直接对应“呼伦贝尔市”。</li>
  <li>第二步是判断输入的地名，它本身或者加个“市”字，是不是恰好准确匹配到一个有效的地名？如果还是没有找到匹配，则进入第三步。</li>
  <li>第三步通过输入城市地名的前两个字和所有标准城市地名的前两个字做模糊匹配，这种方法可以处理“恩施州”到“恩施土家族苗族自治州”这样的转换。虽然我统计发现所有标准地名的前两个字是唯一的，因此这种模糊匹配方法理论上是没有问题的（除了张家口市/张家界市，阿拉尔市/阿拉善盟两对，不过它们会在前面两步中处理掉），但保险起见，最终还是把每次模糊匹配的输入和输出记录下来，我定期会人肉检查确保模糊匹配的正确性。</li>
  <li>最后，对于某些输入，如果经过前三步还没有找到匹配的标准地名，程序会记录下该输入无法被处理，这条病例数据就会被暂时丢弃。我会定期检查这些不能处理的地名，手动加到第一步的规则中，如新疆“第七师”到“塔城地区”这种。</li>
</ul>]]></content><author><name>Zhuo Zhang</name><email>mycinbrin@gmail.com</email></author><summary type="html"><![CDATA[前几天肺炎在全国迅速传播，我会时不时看一下周边城市是不是已经被病毒入侵了。这时我想，如果能做一个地级市的疫情地图，看起来会比读表格方便很多。于是我使用权威媒体的数据绘制了疫情图。最终的网页效果在 这里 。下面记录了一些在此过程中我觉得有意思的细节。]]></summary></entry><entry><title type="html">Topcoder SRM 595 D2L3 LittleElephantAndXor in Haskell</title><link href="https://lispc.github.io/2013/10/26/topcoder-srm-595-d2l3-littleelephantandxor-in-haskell" rel="alternate" type="text/html" title="Topcoder SRM 595 D2L3 LittleElephantAndXor in Haskell" /><published>2013-10-26T00:00:00+00:00</published><updated>2013-10-26T00:00:00+00:00</updated><id>https://lispc.github.io/2013/10/26/topcoder-srm-595-d2l3-littleelephantandxor-in-haskell</id><content type="html" xml:base="https://lispc.github.io/2013/10/26/topcoder-srm-595-d2l3-littleelephantandxor-in-haskell"><![CDATA[<figure class="highlight"><pre><code class="language-haskell" data-lang="haskell"><span class="kr">import</span> <span class="nn">Data.Char</span>
<span class="n">pl</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">]</span> <span class="n">acc</span> <span class="o">=</span> <span class="n">acc</span>
<span class="n">pl</span> <span class="n">ll</span> <span class="n">acc</span> <span class="o">=</span> 
    <span class="n">pl</span> <span class="p">(</span><span class="n">map</span> <span class="p">(</span><span class="n">flip</span> <span class="n">quot</span> <span class="mi">2</span><span class="p">)</span> <span class="n">ll</span><span class="p">)</span> <span class="o">$</span> <span class="n">zipWith</span> <span class="p">(</span><span class="o">$</span><span class="p">)</span> <span class="p">(</span><span class="n">map</span> <span class="p">(</span><span class="nf">\</span><span class="n">x</span> <span class="o">-&gt;</span> <span class="nf">\</span><span class="n">ls</span><span class="o">-&gt;</span><span class="p">(</span><span class="n">mod</span> <span class="n">x</span> <span class="mi">2</span><span class="p">)</span><span class="o">:</span><span class="n">ls</span> <span class="p">)</span><span class="n">ll</span><span class="p">)</span> <span class="n">acc</span>
    
<span class="n">getNumber</span> <span class="o">::</span> <span class="kt">Int</span> <span class="o">-&gt;</span> <span class="kt">Int</span> <span class="o">-&gt;</span> <span class="kt">Int</span> <span class="o">-&gt;</span> <span class="kt">Integer</span>
<span class="n">getNumber</span> <span class="n">a</span> <span class="n">b</span> <span class="n">c</span> <span class="o">=</span> 
    <span class="n">g</span> <span class="n">aa</span> <span class="n">bb</span> <span class="n">cc</span> <span class="n">l</span> 
        <span class="kr">where</span>
            <span class="p">[</span><span class="n">aa</span><span class="p">,</span><span class="n">bb</span><span class="p">,</span><span class="n">cc</span><span class="p">]</span><span class="o">=</span><span class="n">pl</span> <span class="p">[</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">,</span><span class="n">c</span><span class="p">]</span> <span class="p">[</span><span class="kt">[]</span><span class="p">,</span><span class="kt">[]</span><span class="p">,</span><span class="kt">[]</span><span class="p">]</span>
            <span class="n">l</span> <span class="o">=</span> <span class="n">length</span> <span class="n">aa</span>
<span class="n">mo</span> <span class="n">n</span> <span class="o">=</span> <span class="n">take</span> <span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">$</span> <span class="n">repeat</span> <span class="mi">1</span>
<span class="n">gnr</span> <span class="o">::</span> <span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="o">-&gt;</span><span class="kt">Integer</span><span class="o">-&gt;</span><span class="kt">Integer</span>
<span class="n">gnr</span> <span class="kt">[]</span> <span class="n">acc</span> <span class="o">=</span> <span class="n">acc</span>
<span class="n">gnr</span> <span class="p">(</span><span class="n">x</span><span class="o">:</span><span class="n">xs</span><span class="p">)</span> <span class="n">acc</span> <span class="o">=</span> <span class="n">gnr</span> <span class="n">xs</span> <span class="p">((</span><span class="n">fromIntegral</span> <span class="n">x</span><span class="p">)</span><span class="o">+</span><span class="mi">2</span><span class="o">*</span><span class="n">acc</span><span class="p">)</span> 
<span class="n">gn</span> <span class="o">::</span> <span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="o">-&gt;</span><span class="kt">Integer</span>
<span class="n">gn</span> <span class="n">xs</span> <span class="o">=</span> <span class="p">(</span><span class="n">gnr</span> <span class="n">xs</span> <span class="mi">0</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span>
<span class="n">gnm</span> <span class="n">xs</span> <span class="o">=</span> <span class="p">(</span><span class="n">gnr</span> <span class="n">xs</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">g</span> <span class="o">::</span> <span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="o">-&gt;</span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="o">-&gt;</span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="o">-&gt;</span><span class="kt">Int</span><span class="o">-&gt;</span><span class="kt">Integer</span>
<span class="n">g</span> <span class="kt">[]</span> <span class="kt">[]</span> <span class="kt">[]</span> <span class="kr">_</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">g</span> <span class="p">(</span><span class="n">a</span><span class="o">@</span><span class="p">(</span><span class="n">ah</span><span class="o">:</span><span class="n">at</span><span class="p">))</span> <span class="p">(</span><span class="n">b</span><span class="o">@</span><span class="p">(</span><span class="n">bh</span><span class="o">:</span><span class="n">bt</span><span class="p">))</span> <span class="p">(</span><span class="n">c</span><span class="o">@</span><span class="p">(</span><span class="n">ch</span><span class="o">:</span><span class="n">ct</span><span class="p">))</span> <span class="n">l</span> <span class="o">=</span> 
        <span class="kr">case</span> <span class="p">(</span><span class="n">ah</span><span class="p">,</span><span class="n">bh</span><span class="p">,</span><span class="n">ch</span><span class="p">)</span> <span class="kr">of</span>
        <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">g</span> <span class="n">at</span> <span class="n">bt</span> <span class="n">ct</span> <span class="n">ll</span>
        <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">g</span> <span class="n">at</span> <span class="n">bt</span> <span class="n">ml</span> <span class="n">ll</span>
        <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">g</span> <span class="n">at</span> <span class="n">ml</span> <span class="n">ct</span> <span class="n">ll</span>
        <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kr">if</span> <span class="n">l</span><span class="o">==</span><span class="mi">1</span> <span class="kr">then</span> <span class="mi">2</span> <span class="kr">else</span> <span class="p">(</span><span class="n">g</span> <span class="n">at</span> <span class="n">bt</span> <span class="n">ct</span> <span class="n">ll</span><span class="p">)</span><span class="o">+</span><span class="p">((</span><span class="n">gn</span> <span class="n">at</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="mi">2</span><span class="o">^</span><span class="n">ll</span><span class="p">))</span> 
        <span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="kr">_</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">g</span> <span class="n">b</span> <span class="n">a</span> <span class="n">c</span> <span class="n">l</span>
        <span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">gtor</span> <span class="n">ct</span> <span class="n">ll</span><span class="p">)</span><span class="o">+</span><span class="p">(</span><span class="n">g</span> <span class="n">at</span> <span class="n">bt</span> <span class="n">ct</span> <span class="n">ll</span><span class="p">)</span> 
        <span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kr">if</span> <span class="n">l</span><span class="o">==</span><span class="mi">1</span> <span class="kr">then</span> <span class="mi">4</span> <span class="kr">else</span> <span class="p">((</span><span class="mi">2</span><span class="o">^</span><span class="n">ll</span><span class="p">)</span><span class="o">^</span><span class="mi">2</span><span class="p">)</span><span class="o">+</span><span class="p">((</span><span class="n">gn</span> <span class="n">at</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">gn</span> <span class="n">bt</span><span class="p">))</span><span class="o">+</span><span class="p">(</span><span class="n">goor</span> <span class="n">at</span> <span class="n">ct</span> <span class="n">ll</span><span class="p">)</span><span class="o">+</span><span class="p">(</span><span class="n">goor</span> <span class="n">bt</span> <span class="n">ct</span> <span class="n">ll</span><span class="p">)</span>
        <span class="kr">where</span>
                <span class="n">ll</span> <span class="o">=</span> <span class="n">l</span> <span class="o">-</span> <span class="mi">1</span>
                <span class="n">ml</span> <span class="o">=</span> <span class="n">mo</span> <span class="n">l</span>
<span class="n">gtor</span> <span class="kt">[]</span> <span class="kr">_</span>  <span class="o">=</span> <span class="mi">1</span>
<span class="n">gtor</span> <span class="p">(</span><span class="mi">1</span><span class="o">:</span><span class="n">t</span><span class="p">)</span> <span class="n">l</span> <span class="o">=</span> <span class="mi">2</span><span class="o">*</span><span class="p">((</span><span class="mi">2</span><span class="o">^</span><span class="p">(</span><span class="n">l</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span><span class="o">^</span><span class="mi">2</span><span class="p">)</span><span class="o">+</span><span class="mi">2</span><span class="o">*</span><span class="p">(</span><span class="n">gtor</span> <span class="n">t</span> <span class="p">(</span><span class="n">l</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="n">gtor</span> <span class="p">(</span><span class="mi">0</span><span class="o">:</span><span class="n">t</span><span class="p">)</span> <span class="n">l</span> <span class="o">=</span> <span class="mi">2</span><span class="o">*</span><span class="p">(</span><span class="n">gtor</span> <span class="n">t</span> <span class="p">(</span><span class="n">l</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span> 
<span class="n">goor</span> <span class="kt">[]</span> <span class="kt">[]</span> <span class="kr">_</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">goor</span> <span class="n">b</span><span class="o">@</span><span class="p">(</span><span class="n">bh</span><span class="o">:</span><span class="n">bt</span><span class="p">)</span> <span class="n">c</span><span class="o">@</span><span class="p">(</span><span class="n">ch</span><span class="o">:</span><span class="n">ct</span><span class="p">)</span> <span class="n">l</span> <span class="o">=</span>
    <span class="kr">case</span> <span class="p">(</span><span class="n">bh</span><span class="p">,</span><span class="n">ch</span><span class="p">)</span> <span class="kr">of</span>
        <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">goor</span> <span class="n">bt</span> <span class="n">ct</span> <span class="n">ll</span>
        <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="mi">2</span><span class="o">^</span><span class="n">ll</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">gn</span> <span class="n">bt</span><span class="p">)</span><span class="o">+</span><span class="p">(</span><span class="n">goor</span> <span class="n">bt</span> <span class="n">ct</span> <span class="n">ll</span><span class="p">)</span>
        <span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">goor</span> <span class="n">bt</span> <span class="n">ct</span> <span class="n">ll</span><span class="p">)</span><span class="o">+</span><span class="p">(</span><span class="n">gtor</span> <span class="n">ct</span> <span class="n">ll</span><span class="p">)</span>
        <span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="mi">2</span><span class="o">^</span><span class="n">ll</span><span class="p">)</span><span class="o">^</span><span class="mi">2</span><span class="o">+</span><span class="p">(</span><span class="n">goor</span> <span class="n">bt</span> <span class="n">ct</span> <span class="n">ll</span><span class="p">)</span><span class="o">+</span><span class="p">(</span><span class="n">gtor</span> <span class="n">ct</span> <span class="n">ll</span><span class="p">)</span><span class="o">+</span><span class="p">(</span><span class="mi">2</span><span class="o">^</span><span class="n">ll</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">gn</span> <span class="n">bt</span><span class="p">)</span>
        <span class="kr">where</span> <span class="n">ll</span><span class="o">=</span><span class="n">l</span><span class="o">-</span><span class="mi">1</span></code></pre></figure>]]></content><author><name>Zhuo Zhang</name><email>mycinbrin@gmail.com</email></author><summary type="html"><![CDATA[import Data.Char pl [0,0,0] acc = acc pl ll acc = pl (map (flip quot 2) ll) $ zipWith ($) (map (\x -&gt; \ls-&gt;(mod x 2):ls )ll) acc getNumber :: Int -&gt; Int -&gt; Int -&gt; Integer getNumber a b c = g aa bb cc l where [aa,bb,cc]=pl [a,b,c] [[],[],[]] l = length aa mo n = take (n-1) $ repeat 1 gnr :: [Int]-&gt;Integer-&gt;Integer gnr [] acc = acc gnr (x:xs) acc = gnr xs ((fromIntegral x)+2*acc) gn :: [Int]-&gt;Integer gn xs = (gnr xs 0)+1 gnm xs = (gnr xs 0) g :: [Int]-&gt;[Int]-&gt;[Int]-&gt;Int-&gt;Integer g [] [] [] _ = 1 g (a@(ah:at)) (b@(bh:bt)) (c@(ch:ct)) l = case (ah,bh,ch) of (0,0,0) -&gt; g at bt ct ll (0,0,1) -&gt; g at bt ml ll (0,1,0) -&gt; g at ml ct ll (0,1,1) -&gt; if l==1 then 2 else (g at bt ct ll)+((gn at)*(2^ll)) (1,0,_) -&gt; g b a c l (1,1,0) -&gt; (gtor ct ll)+(g at bt ct ll) (1,1,1) -&gt; if l==1 then 4 else ((2^ll)^2)+((gn at)*(gn bt))+(goor at ct ll)+(goor bt ct ll) where ll = l - 1 ml = mo l gtor [] _ = 1 gtor (1:t) l = 2*((2^(l-1))^2)+2*(gtor t (l-1)) gtor (0:t) l = 2*(gtor t (l-1)) goor [] [] _ = 1 goor b@(bh:bt) c@(ch:ct) l = case (bh,ch) of (0,0) -&gt; goor bt ct ll (0,1) -&gt; (2^ll)*(gn bt)+(goor bt ct ll) (1,0) -&gt; (goor bt ct ll)+(gtor ct ll) (1,1) -&gt; (2^ll)^2+(goor bt ct ll)+(gtor ct ll)+(2^ll)*(gn bt) where ll=l-1]]></summary></entry><entry><title type="html">How to do LRU cache in Haskell</title><link href="https://lispc.github.io/2013/10/23/how-to-do-lru-cache-in-haskell" rel="alternate" type="text/html" title="How to do LRU cache in Haskell" /><published>2013-10-23T00:00:00+00:00</published><updated>2013-10-23T00:00:00+00:00</updated><id>https://lispc.github.io/2013/10/23/how-to-do-lru-cache-in-haskell</id><content type="html" xml:base="https://lispc.github.io/2013/10/23/how-to-do-lru-cache-in-haskell"><![CDATA[<figure class="highlight"><pre><code class="language-haskell" data-lang="haskell"><span class="kr">import</span> <span class="k">qualified</span> <span class="nn">Data.Map</span> <span class="k">as</span> <span class="n">M</span>
<span class="kr">import</span> <span class="k">qualified</span> <span class="nn">Data.PQueue.Min</span> <span class="k">as</span> <span class="n">PQ</span>
<span class="n">fib</span> <span class="mi">0</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">fib</span> <span class="mi">1</span> <span class="o">=</span> <span class="mi">1</span> 
<span class="n">fib</span> <span class="n">n</span> <span class="o">=</span> <span class="p">(</span><span class="n">fib</span> <span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span><span class="o">+</span><span class="p">(</span><span class="n">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">2</span><span class="p">))</span>
<span class="n">maxsize</span> <span class="o">=</span> <span class="mi">1000</span> 
<span class="kr">type</span> <span class="kt">FKey</span> <span class="o">=</span> <span class="kt">Int</span> 
<span class="kr">type</span> <span class="kt">FVal</span> <span class="o">=</span> <span class="kt">Int</span>
<span class="kr">type</span> <span class="kt">MyF</span> <span class="o">=</span> <span class="kt">FKey</span><span class="o">-&gt;</span><span class="kt">FVal</span>
<span class="kr">type</span> <span class="kt">TimeStamp</span> <span class="o">=</span> <span class="kt">Int</span>
<span class="kr">type</span> <span class="kt">Cache</span> <span class="o">=</span> <span class="p">(</span><span class="kt">M</span><span class="o">.</span><span class="kt">Map</span> <span class="kt">FKey</span> <span class="p">(</span><span class="kt">FVal</span><span class="p">,</span><span class="kt">TimeStamp</span><span class="p">),</span> <span class="kt">M</span><span class="o">.</span><span class="kt">Map</span> <span class="kt">TimeStamp</span> <span class="kt">FKey</span><span class="p">,</span><span class="kt">TimeStamp</span><span class="p">)</span> 
<span class="n">cacheWithLimitSpace</span> <span class="n">f</span> <span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="n">q</span><span class="p">,</span><span class="n">lastt</span><span class="p">)</span> <span class="n">k</span> <span class="o">=</span>
    <span class="kr">case</span> <span class="kt">M</span><span class="o">.</span><span class="n">lookup</span> <span class="n">k</span> <span class="n">m</span> <span class="kr">of</span>
        <span class="kt">Just</span> <span class="p">(</span><span class="n">r</span><span class="p">,</span><span class="n">oldt</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="c1">--(((M.insert k (r,(t+1)) m),q),r)</span>
            <span class="kr">let</span> <span class="n">newt</span> <span class="o">=</span> <span class="n">lastt</span><span class="o">+</span><span class="mi">1</span> <span class="kr">in</span>
            <span class="kr">let</span> <span class="n">newm</span> <span class="o">=</span> <span class="kt">M</span><span class="o">.</span><span class="n">insert</span> <span class="n">k</span> <span class="p">(</span><span class="n">r</span><span class="p">,</span><span class="n">newt</span><span class="p">)</span> <span class="n">m</span> <span class="kr">in</span>
            <span class="kr">let</span> <span class="n">newq</span> <span class="o">=</span> <span class="kt">M</span><span class="o">.</span><span class="n">insert</span> <span class="n">newt</span> <span class="n">k</span> <span class="p">(</span><span class="kt">M</span><span class="o">.</span><span class="n">delete</span> <span class="n">oldt</span> <span class="n">q</span><span class="p">)</span> <span class="kr">in</span>
            <span class="p">((</span><span class="n">newm</span><span class="p">,</span><span class="n">newq</span><span class="p">,</span><span class="n">newt</span><span class="p">),</span><span class="n">r</span><span class="p">)</span>
        <span class="kt">Nothing</span> <span class="o">-&gt;</span> 
            <span class="kr">let</span> <span class="n">r</span> <span class="o">=</span> <span class="n">f</span> <span class="n">k</span> <span class="kr">in</span>
            <span class="kr">if</span> <span class="p">(</span><span class="kt">M</span><span class="o">.</span><span class="n">size</span> <span class="n">m</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">lt</span><span class="p">;</span> <span class="n">maxsize</span>
                <span class="kr">then</span> 
                    <span class="kr">let</span> <span class="n">newt</span> <span class="o">=</span> <span class="n">lastt</span><span class="o">+</span><span class="mi">1</span> <span class="kr">in</span>
                    <span class="kr">let</span> <span class="n">newm</span> <span class="o">=</span> <span class="kt">M</span><span class="o">.</span><span class="n">insert</span> <span class="n">k</span> <span class="p">(</span><span class="n">r</span><span class="p">,</span><span class="n">newt</span><span class="p">)</span> <span class="n">m</span> <span class="kr">in</span><span class="c1">--),q,t+1),r)</span>
                    <span class="kr">let</span> <span class="n">newq</span> <span class="o">=</span> <span class="kt">M</span><span class="o">.</span><span class="n">insert</span> <span class="n">newt</span> <span class="n">k</span> <span class="n">q</span> <span class="kr">in</span>
                    <span class="p">((</span><span class="n">newm</span><span class="p">,</span><span class="n">newq</span><span class="p">,</span><span class="n">newt</span><span class="p">),</span><span class="n">r</span><span class="p">)</span>
                <span class="kr">else</span> 
                    <span class="kr">let</span> <span class="n">newt</span> <span class="o">=</span> <span class="n">lastt</span><span class="o">+</span><span class="mi">1</span> <span class="kr">in</span>
                    <span class="kr">let</span> <span class="p">((</span><span class="kr">_</span><span class="p">,</span><span class="n">invalidKey</span><span class="p">),</span><span class="n">q'</span><span class="p">)</span> <span class="o">=</span> <span class="kt">M</span><span class="o">.</span><span class="n">deleteFindMin</span> <span class="n">q</span> <span class="kr">in</span>
                    <span class="kr">let</span> <span class="n">newm</span> <span class="o">=</span> <span class="kt">M</span><span class="o">.</span><span class="n">insert</span> <span class="n">k</span> <span class="p">(</span><span class="n">r</span><span class="p">,</span><span class="n">newt</span><span class="p">)</span> <span class="p">(</span><span class="kt">M</span><span class="o">.</span><span class="n">delete</span> <span class="n">invalidKey</span> <span class="n">m</span><span class="p">)</span> <span class="kr">in</span>
                    <span class="kr">let</span> <span class="n">newq</span> <span class="o">=</span> <span class="kt">M</span><span class="o">.</span><span class="n">insert</span> <span class="n">newt</span> <span class="n">k</span> <span class="n">q'</span> <span class="kr">in</span>
                    <span class="p">((</span><span class="n">newm</span><span class="p">,</span><span class="n">newq</span><span class="p">,</span><span class="n">newt</span><span class="p">),</span><span class="n">r</span><span class="p">)</span>
<span class="n">tint</span><span class="o">=</span><span class="mi">35</span>
<span class="n">main</span> <span class="o">=</span> <span class="kr">do</span>
    <span class="n">print</span> <span class="o">$</span> <span class="n">fib</span> <span class="n">tint</span>
    <span class="n">print</span> <span class="o">$</span> <span class="n">fib</span> <span class="n">tint</span>
    <span class="kr">let</span> <span class="p">(</span><span class="n">c</span><span class="p">,</span><span class="n">r1</span><span class="p">)</span> <span class="o">=</span> <span class="n">cacheWithLimitSpace</span> <span class="n">fib</span> <span class="p">(</span><span class="kt">M</span><span class="o">.</span><span class="n">empty</span><span class="p">,</span> <span class="kt">M</span><span class="o">.</span><span class="n">empty</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="n">tint</span>
    <span class="n">print</span> <span class="n">r1</span>
    <span class="kr">let</span> <span class="p">(</span><span class="kr">_</span><span class="p">,</span><span class="n">r2</span><span class="p">)</span> <span class="o">=</span> <span class="n">cacheWithLimitSpace</span> <span class="n">fib</span> <span class="n">c</span> <span class="n">tint</span>
    <span class="n">print</span> <span class="n">r2</span></code></pre></figure>]]></content><author><name>Zhuo Zhang</name><email>mycinbrin@gmail.com</email></author><summary type="html"><![CDATA[import qualified Data.Map as M import qualified Data.PQueue.Min as PQ fib 0 = 1 fib 1 = 1 fib n = (fib (n-1))+(fib(n-2)) maxsize = 1000 type FKey = Int type FVal = Int type MyF = FKey-&gt;FVal type TimeStamp = Int type Cache = (M.Map FKey (FVal,TimeStamp), M.Map TimeStamp FKey,TimeStamp) cacheWithLimitSpace f (m,q,lastt) k = case M.lookup k m of Just (r,oldt) -&gt; --(((M.insert k (r,(t+1)) m),q),r) let newt = lastt+1 in let newm = M.insert k (r,newt) m in let newq = M.insert newt k (M.delete oldt q) in ((newm,newq,newt),r) Nothing -&gt; let r = f k in if (M.size m) &amp;lt; maxsize then let newt = lastt+1 in let newm = M.insert k (r,newt) m in--),q,t+1),r) let newq = M.insert newt k q in ((newm,newq,newt),r) else let newt = lastt+1 in let ((_,invalidKey),q') = M.deleteFindMin q in let newm = M.insert k (r,newt) (M.delete invalidKey m) in let newq = M.insert newt k q' in ((newm,newq,newt),r) tint=35 main = do print $ fib tint print $ fib tint let (c,r1) = cacheWithLimitSpace fib (M.empty, M.empty, 0) tint print r1 let (_,r2) = cacheWithLimitSpace fib c tint print r2]]></summary></entry><entry><title type="html">一万个小时，兴趣，性价比</title><link href="https://lispc.github.io/2013/10/22/" rel="alternate" type="text/html" title="一万个小时，兴趣，性价比" /><published>2013-10-22T00:00:00+00:00</published><updated>2013-10-22T00:00:00+00:00</updated><id>https://lispc.github.io/2013/10/</id><content type="html" xml:base="https://lispc.github.io/2013/10/22/"><![CDATA[<p>今天在机房被一个同学问怎么安装flex，就顺便讲了一下linux包管理机制和用户系统．然后是：＂这些东西你怎么知道的，或者，怎么学？＂我当时给出了一个经典正确但无用的回答：＂玩多了自然就会了．＂</p>

<p>之后就一直在想，怎么才是学习这些零碎知识的最佳方式．但我记起来的，多是在609A装电脑修电脑的晚上，以及这三年来耗在错误上的无数时间．并没有刻意去看书学习，但一年来积累的三万次搜索提供了种种知识．</p>

<p>而这一切都并不是有意计划的，大多是作为爱好和消遣．作为爱好的事情，从来不会衡量投入的时间是否值得，事实上投入的时间之大使得所谓＂性价比＂极低．任何事情的边际学习效率都是递减的，所以要做好需要相当大的精力．此时的性价比会远远低于我们脑海中的预期．所以每当我精打细算一件事情做不做的时候，这件事情就不可能做好．因为我会犹豫投入这么大精力是否值得，首鼠两端不愿付出．但真正喜欢一件事的时候，它会填充你所有的空闲时间．比如昨天晚上从港大回施德的路上一直在想Euler375那道数论题，恨不得立刻vim 375.hs动笔写．当然，你付出的时间其实大多数都沉默掉了，永远永远不会回报．比如给显卡装GPGPU驱动啊，配置环境这些一次性的工作．</p>

<p>##但是，那些沉默的成本，无用的付出，总是做好一件事所必要的．</p>

<p>我的大学最初便竭力试图找到一条正确笔直的路，不做任何的浪费．于是大一的时候就为carrer path这种事情耽精竭虑．总是因为担心一件事情不值而不愿付出，最终却总是做不好．Rj同学在609A被称为＂每一次见到你，都在代码里＂，最终Rj的技术进步速度也是相当之快，半年前我在Rj的电脑上图形界面装Opensuse，敲configure make install，半年后就是Rj帮我装archlinux敲chroot mount mkfs了．这一切都归功于Rj桌上的山一样的书和一个个对着自己电脑敲键盘的晚上．前几天Rj发了一条状态，大意是犯了个低端错误浪费了几个小时，同为码农会心一笑，浪费几个小时真是太容易了．要不是前几天浪费在socket上的几个小时，怎么会知道linux tcp端口owner突然be killed之后几十秒之内不能重新bind这种细节？</p>

<p>b******k和b****d那一堆耀眼的项目背后不是有很多不那么耀眼的项目么．．<br />
Philip Guo不是在斯坦福蹉跎了三年搬砖被砸无数次才找到方向的么．．</p>

<p>##不过呢，作为任务而不是兴趣的事情，人们却多做不到不计成本的付出，所以说，或许只有那些真正喜欢的事情，你才能坚持付出一万个小时，把它做好．</p>

<hr />

<p>写这篇blog的时候又google了markdown的一些用法，当然，不少之前google过，并且用过，这也算性价比不高的付出了吧．<br />
减少焦虑的两种方法，提升实力，降低期望． <br />
谁的事业不从搬砖始．<br />
自己安安静静地做该做的事，莫问前程． <br />
明天好运．</p>]]></content><author><name>Zhuo Zhang</name><email>mycinbrin@gmail.com</email></author><summary type="html"><![CDATA[今天在机房被一个同学问怎么安装flex，就顺便讲了一下linux包管理机制和用户系统．然后是：＂这些东西你怎么知道的，或者，怎么学？＂我当时给出了一个经典正确但无用的回答：＂玩多了自然就会了．＂]]></summary></entry><entry><title type="html">Y Combinator</title><link href="https://lispc.github.io/2013/10/07/y-combinator" rel="alternate" type="text/html" title="Y Combinator" /><published>2013-10-07T00:00:00+00:00</published><updated>2013-10-07T00:00:00+00:00</updated><id>https://lispc.github.io/2013/10/07/y-combinator</id><content type="html" xml:base="https://lispc.github.io/2013/10/07/y-combinator"><![CDATA[<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1">#! /usr/bin/env python3
</span><span class="n">Y</span><span class="o">=</span><span class="k">lambda</span> <span class="n">F</span><span class="p">:(</span>\
        <span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="p">(</span>\
            <span class="nc">F</span><span class="p">(</span><span class="k">lambda</span> <span class="n">y</span><span class="p">:((</span><span class="nf">x</span><span class="p">(</span><span class="n">x</span><span class="p">))(</span><span class="n">y</span><span class="p">)))</span>\
            <span class="p">))</span>\
        <span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="p">(</span>\
            <span class="nc">F</span><span class="p">(</span><span class="k">lambda</span> <span class="n">y</span><span class="p">:((</span><span class="nf">x</span><span class="p">(</span><span class="n">x</span><span class="p">))(</span><span class="n">y</span><span class="p">)))</span>\
            <span class="p">))</span>\
        <span class="p">)</span>
<span class="n">FactGen</span><span class="o">=</span><span class="k">lambda</span> <span class="n">fact</span><span class="p">:(</span>\
        <span class="p">(</span><span class="k">lambda</span> <span class="n">n</span><span class="p">:(</span>\
            <span class="p">(</span><span class="mi">1</span> <span class="k">if</span> <span class="n">n</span><span class="o">==</span><span class="mi">0</span> <span class="k">else</span> <span class="n">n</span><span class="o">*</span><span class="nf">fact</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span>\
            <span class="p">)</span>\
        <span class="p">))</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">list</span><span class="p">(</span><span class="nf">map</span><span class="p">(</span><span class="nc">Y</span><span class="p">(</span><span class="n">FactGen</span><span class="p">),(</span><span class="nf">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">10</span><span class="p">)))))</span></code></pre></figure>]]></content><author><name>Zhuo Zhang</name><email>mycinbrin@gmail.com</email></author><summary type="html"><![CDATA[#! /usr/bin/env python3 Y=lambda F:(\ (lambda x: (\ F(lambda y:((x(x))(y)))\ ))\ (lambda x: (\ F(lambda y:((x(x))(y)))\ ))\ ) FactGen=lambda fact:(\ (lambda n:(\ (1 if n==0 else n*fact(n - 1))\ )\ )) print(list(map(Y(FactGen),(range(1,10)))))]]></summary></entry><entry><title type="html">Learning Blender</title><link href="https://lispc.github.io/2013/06/17/learning-blender" rel="alternate" type="text/html" title="Learning Blender" /><published>2013-06-17T00:00:00+00:00</published><updated>2013-06-17T00:00:00+00:00</updated><id>https://lispc.github.io/2013/06/17/learning-blender</id><content type="html" xml:base="https://lispc.github.io/2013/06/17/learning-blender"><![CDATA[<p>It is the first time that I really use a 3D-modeling software. I choose <a href="http://www.blender.org">Blender</a> since it is an open-source sofware with full-featured python script support which is very useful for a programmmer like me, besides, it is as powerful as business softwares like 3DMAX.
I find <a href="http://www.youtube.com/watch?v=y__uzGKmxt8">a video in youtube</a> is a very good learing resource for newbies. I just followed the tutorial and below are my result.</p>

<p><img src="/assets/images/cup_line.png" alt="a" />
<img src="/assets/images/cup_solid.png" alt="a" />
<img src="/assets/images/cup_smooth.png" alt="a" />
<img src="/assets/images/cup_render.png" alt="a" /></p>]]></content><author><name>Zhuo Zhang</name><email>mycinbrin@gmail.com</email></author><category term="design" /><summary type="html"><![CDATA[It is the first time that I really use a 3D-modeling software. I choose Blender since it is an open-source sofware with full-featured python script support which is very useful for a programmmer like me, besides, it is as powerful as business softwares like 3DMAX. I find a video in youtube is a very good learing resource for newbies. I just followed the tutorial and below are my result.]]></summary></entry></feed>