Work miracles, combinatorial math calculator

Effect

Calculate the next permutation for different generation algorithms based on permutations

There are two modes, input arrangement and input ordinal. Since the intermediate number cannot guarantee the existence of the three at the same time, I am too lazy to do it.....

At present, only the common 9 bits are made, and I am too lazy to support any bits. . . . (mostly nine in the main work)

In terms of speed, since all permutations are calculated during operation, the initial loading is relatively slow. It can be persisted as a json file and loaded directly. When searching for permutations, efficient binary search can be used to shorten the search time.

In terms of data structure, for output in tabular format, a conversion function should be set to convert the object to the required format

Utility functions can be integrated into an object to directly call static methods

 

 

tool

// 获取长度为len的所有排列,按照字典序
function getAllRange(len) {
  let a = []
  let MAX = len
  let used = new Set()
  let ALL = []

  dfs(0)

  function dfs(n) {
    if (n == MAX) {
      // console.log(a)
      ALL.push(Array.from(a))
      used.delete(a.pop())
      return
    }

    for (let i = 1; i <= MAX; i++) {
      if (!used.has(i)) {
        a.push(i)
        used.add(i)
        dfs(n + 1)
      }
    }

    used.delete(a.pop())
  }

  return ALL
}

// 阶乘
function fac(n) {
  return n < 2 ? 1 : n * fac(n - 1)
}

// 字典序中介数计算
function f1(arr) {
  let ret = []
  for (let i = 0; i < arr.length; i++) {
    let c = 0
    for (let j = i + 1; j < arr.length; j++)
      arr[j] < arr[i] ? c++ : c
    ret[i] = c
  }

  return ret.slice(0, arr.length - 1)
}

// 字典序中介数求序数
function getM1(arr) {
  return arr.reduce(
    (pre, cur, index) => pre + cur * fac(arr.length - index),
    0
  )
}

// 递增排列转中介数
function f2(arr) {
  let ret = []
  for (let i = 0; i < arr.length; i++) {
    let c = 0
    for (let j = i + 1; j < arr.length; j++)
      arr[j] < arr[i] ? c++ : c
    ret[arr[i] - 1] = c
  }

  return ret.reverse().slice(0, arr.length - 1)
}

// 递增中介数求序数
function getM2(a) {
  return a.reduce(
    (pre, cur, index) => pre + cur * fac(a.length - index),
    0
  )
}

// 递减中介数求序数
function getM3(a, len) {
  let pre = a[0]
  for (let i = 1; i < a.length; i++) {
    pre = pre * (len - a.length + 1 + i) + a[i]
  }
  return pre
}

function getData(len) {
  let data = {
    inc: {},
    dec: {},
    dic: {}
  }

  let range = getAllRange(len)
  for (let i of range) {

    // 递增的中介数和序数
    data['inc'][i.join('')] = {}
    data['inc'][i.join('')]['mid'] = parseInt(f2(i).join(''))
    data['inc'][i.join('')]['num'] = getM2(f2(i))
    data['inc'][i.join('')]['range'] = i.join('')
    // 递减
    data['dec'][i.join('')] = {}
    data['dec'][i.join('')]['mid'] = parseInt(f2(i).reverse().join(''))
    data['dec'][i.join('')]['num'] = getM3(f2(i).reverse(), len)
    data['dec'][i.join('')]['range'] = i.join('')

    // 字典
    data['dic'][i.join('')] = {}
    data['dic'][i.join('')]['mid'] = parseInt(f1(i).join(''))
    data['dic'][i.join('')]['num'] = getM1(f1(i))
    data['dic'][i.join('')]['range'] = i.join('')

  }

  return data
}

// 字典序下一个排列
function next1(arr) {
  let num = d['dic'][arr]['num']
  console.log(num + 1)
  for (let i in d['dic']) {
    if (d['dic'][i]['num'] == num + 1) {
      console.log(i)
      return {
        key: i,
        num: d['dic'][i]['num'] + 1,
        mid: d['dic'][i]['mid']
      }
    }
  }
}


let d = getData(9)

// 递增序下一个排列
function next2(arr) {
  console.log(d['inc'][arr])
  let num = 1 + d['inc'][arr]['num']
  console.log(num)

  for (let i in d['inc']) {
    if (d['inc'][i]['num'] == num) {
      console.log(i)
      return {
        key: i,
        num: d['inc'][i]['num'],
        mid: d['inc'][i]['mid']
      }
    }
  }
}

// 递减序下一个排列
function next3(arr) {
  console.log(d['dec'][arr])
  let num = 1 + d['dec'][arr]['num']
  console.log(num)

  for (let i in d['dec']) {
    if (d['dec'][i]['num'] == num) {
      console.log(i)
      return {
        key: i,
        num: d['dec'][i]['num'],
        mid: d['dec'][i]['mid']
      }
    }
  }
}

// 递增进制的加法,低位逢二进一,依次递增
function inc1(num) {
  let a = Array.from('' + num).map(cur => cur - '').reverse()
  // console.log(a);
  let c = 1
  for (let i = 0; i < a.length; i++) {
    let s = (a[i] + c)
    a[i] = s % (i + 2)
    c = Math.floor(s / (i + 2))
  }
  if (c == 1) {
    a[a.length] = 1
  }
  console.log(a);
  return parseInt(a.reverse().join(''))
}

// 递减进制的加法,低位逢九进一,依次递减
function inc2(num, len = 9) {
  let a = Array.from('' + num).map(cur => cur - '').reverse()
  // console.log(a);
  let c = 1
  for (let i = 0; i < a.length; i++) {
    let s = (a[i] + c)
    a[i] = s % (len - i)
    c = Math.floor(s / (len - i))
  }
  if (c == 1) {
    a[a.length] = 1
  }
  console.log(a);
  return parseInt(a.reverse().join(''))
}

export {
  d,
  next1,
  next2,
  next3,
}

 

ui

<template>
  <div class="main">
    <el-form ref="form" :model="form" label-width="80px" style="width: 300px">
      <el-form-item label="位数">
        <el-select v-model="form.len">
          <el-option v-for="i in 9" :label="i" :value="i" :key="i"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="类型">
        <el-select v-model="form.type">
          <el-option label="序数" :value="0"></el-option>
          <!--<el-option label="中介数" :value="1"></el-option>-->
          <el-option label="排列" :value="2"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="数据">
        <el-input v-model="form.input" placeholder="请输入数据" @keyup.enter.native="onSubmit"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSubmit">submit</el-button>
      </el-form-item>
    </el-form>

    <table class="table table-bordered table-striped  " style="width: 800px;text-align: center">
      <thead>
      <tr>
        <th></th>
        <th>增序</th>
        <th>逆序</th>
        <th>字典序</th>
      </tr>
      </thead>
      <tbody>
      <tr v-for="i,index in tableData">
        <th scope="row">{{cols[index]}}</th>
        <td>{{tableData[index][0]}}</td>
        <td>{{tableData[index][1]}}</td>
        <td>{{tableData[index][2]}}</td>
      </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
  import {next1, next2, next3, d} from '../util'
  import 'bootstrap/dist/css/bootstrap.css'

  export default {
    name: "main-view",

    methods: {
      // 对应不同类型的处理函数,返回一个对象
      f0() {
        // 输入的是序数 232450
        let cur_inc, cur_dec, cur_dic
        let next_inc, next_dec, next_dic
        for (let i in d['inc']) {
          if (d['inc'][i]['num'] == this.form.input) {
            cur_inc = d['inc'][i]
            break
          }
        }

        for (let i in d['dec']) {
          if (d['dec'][i]['num'] == this.form.input) {
            cur_dec = d['dec'][i]
            break
          }
        }
        for (let i in d['dic']) {
          if (d['inc'][i]['num'] == this.form.input) {
            cur_dic = d['dic'][i]
            break
          }
        }

        for (let i in d['inc']) {
          if (d['inc'][i]['num'] == cur_inc['num'] + 1) {
            next_inc = d['inc'][i]
            break
          }
        }

        for (let i in d['dec']) {
          if (d['dec'][i]['num'] == cur_dec['num'] + 1) {
            next_dec = d['dec'][i]
            break
          }
        }
        for (let i in d['dic']) {
          if (d['dic'][i]['num'] == cur_dic['num'] + 1) {
            next_dic = d['dic'][i]
            break
          }
        }
        return [
          [cur_inc['num'], cur_dec['num'], cur_dic['num']],
          [cur_inc['mid'], cur_dec['mid'], cur_dic['mid']],
          [cur_inc.range, cur_dec.range, cur_dic.range],
          [next_inc['num'], next_dec.num, next_dic.num],
          [next_inc.mid, next_dec.mid, next_dic.mid],
          [next_inc.range, next_dec.range, next_dic.range],
        ]
      },
      f1() {
        // 输入的是中介数

      },
      f2() {
        // 输入的是排列  //632589714

        let cur_inc = d['inc'][this.form.input]
        let cur_dec = d['dec'][this.form.input]
        let cur_dic = d['dic'][this.form.input]
        let next_inc, next_dec, next_dic
        for (let i in d['inc']) {
          if (d['inc'][i]['num'] == cur_inc['num'] + 1) {
            next_inc = d['inc'][i]
            break
          }
        }

        for (let i in d['dec']) {
          if (d['dec'][i]['num'] == cur_dec['num'] + 1) {
            next_dec = d['dec'][i]
            break
          }
        }
        for (let i in d['dic']) {
          if (d['dic'][i]['num'] == cur_dic['num'] + 1) {
            next_dic = d['dic'][i]
            break
          }
        }
        return [
          [cur_inc['num'], cur_dec['num'], cur_dic['num']],
          [cur_inc['mid'], cur_dec['mid'], cur_dic['mid']],
          [cur_inc.range, cur_dec.range, cur_dic.range],
          [next_inc['num'], next_dec.num, next_dic.num],
          [next_inc.mid, next_dec.mid, next_dic.mid],
          [next_inc.range, next_dec.range, next_dic.range],
        ]
      },
      // 执行查询显示结果
      onSubmit() {
        this.tableData = [this.f0, this.f1, this.f2][this.form.type]()
      }
    },
    data() {
      return {
        cols: ['当前序数', '当前中介数', '当前排序', '下一序数', '下一中介数', '下一排序'],
        form: {
          len: 9,
          type: 2,
          input: ''
        },
        tableData: Array(6).fill([]),
      }
    }
  }
</script>

<style scoped>
  .main {
    width: 100vw;
    height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  }
</style>

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325291728&siteId=291194637